如何导入给定相对路径的Python模块?

例如,如果dirFoo包含Foo.py和dirBar,而dirBar包含Bar.py,我如何将Bar.py导入Foo.py?

下面是一个视觉表示:

dirFoo\
    Foo.py
    dirBar\
        Bar.py

Foo希望包含Bar,但重组文件夹层次结构不是一个选项。


当前回答

确保dirBar具有__init__.py文件——这会将一个目录放入Python包中。

其他回答

假设您的两个目录都是真正的Python包(其中确实包含__init__.py文件),这里有一个相对于脚本位置包含模块的安全解决方案。

我假设您想这样做,因为您需要在脚本中包含一组模块。我在一些产品的生产中使用了这一点,并在许多特殊场景中工作,例如:从另一个目录调用或使用python执行的脚本,而不是打开新的解释器。

 import os, sys, inspect
 # realpath() will make your script run, even if you symlink it :)
 cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
 if cmd_folder not in sys.path:
     sys.path.insert(0, cmd_folder)

 # Use this if you want to include modules from a subfolder
 cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"subfolder")))
 if cmd_subfolder not in sys.path:
     sys.path.insert(0, cmd_subfolder)

 # Info:
 # cmd_folder = os.path.dirname(os.path.abspath(__file__)) # DO NOT USE __file__ !!!
 # __file__ fails if the script is called in different ways on Windows.
 # __file__ fails if someone does os.chdir() before.
 # sys.argv[0] also fails, because it doesn't not always contains the path.

另外,这种方法允许您强制Python使用您的模块,而不是安装在系统上的模块。

警告我真的不知道当当前模块在蛋文件中时会发生什么。它可能也会失败。

import os
import sys
lib_path = os.path.abspath(os.path.join(__file__, '..', '..', '..', 'lib'))
sys.path.append(lib_path)

import mymodule

最简单的方法是使用sys.path.append()。

然而,您可能也对imp模块感兴趣。它提供对内部导入功能的访问。

# mod_name is the filename without the .py/.pyc extention
py_mod = imp.load_source(mod_name,filename_path) # Loads .py file
py_mod = imp.load_compiled(mod_name,filename_path) # Loads .pyc file 

当您不知道模块的名称时,这可以用于动态加载模块。

我在过去使用过这个来创建应用程序的插件类型接口,用户可以在其中编写带有应用程序特定函数的脚本,然后将脚本放到特定目录中。

此外,这些功能可能有用:

imp.find_module(name[, path])
imp.load_module(name, file, pathname, description)

在我看来,最好的选择是将__init__.py放在文件夹中,并使用

from dirBar.Bar import *

不建议使用sys.path.append(),因为如果使用与现有python包相同的文件名,可能会出现问题。我还没有测试过,但这将是模棱两可的。

嗯,正如您所提到的,通常您希望能够访问与主脚本运行位置相关的模块文件夹,因此只需导入它们。

解决方案:

我有D:/Books/MyBooks.py中的脚本和一些模块(如oldies.py)。我需要从子目录D:/Books/includes导入:

import sys,site
site.addsitedir(sys.path[0] + '\\includes')
print (sys.path)  # Just verify it is there
import oldies

在oldies.py中放置一个打印(“done”),这样您就可以验证一切正常。这种方式总是有效的,因为根据程序启动时初始化的Python定义sys.path,此列表的第一项路径[0]是包含用于调用Python解释器的脚本的目录。

如果脚本目录不可用(例如,如果以交互方式调用解释器或从标准输入读取脚本),则路径[0]是空字符串,它指示Python首先搜索当前目录中的模块。请注意,脚本目录是在PYTHONPATH插入的条目之前插入的。