如何导入给定相对路径的Python模块?
例如,如果dirFoo包含Foo.py和dirBar,而dirBar包含Bar.py,我如何将Bar.py导入Foo.py?
下面是一个视觉表示:
dirFoo\
Foo.py
dirBar\
Bar.py
Foo希望包含Bar,但重组文件夹层次结构不是一个选项。
如何导入给定相对路径的Python模块?
例如,如果dirFoo包含Foo.py和dirBar,而dirBar包含Bar.py,我如何将Bar.py导入Foo.py?
下面是一个视觉表示:
dirFoo\
Foo.py
dirBar\
Bar.py
Foo希望包含Bar,但重组文件夹层次结构不是一个选项。
当前回答
最简单的方法是使用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)
其他回答
不修改脚本的最简单方法是设置PYTHONPATH环境变量。因为sys.path是从以下位置初始化的:
包含输入脚本的目录(或当前目录)。PYTHONPATH(目录名列表,与语法作为外壳变量PATH)。依赖于安装的默认值。
只需运行:
export PYTHONPATH=/absolute/path/to/your/module
sys.path将包含上述路径,如下所示:
print sys.path
['', '/absolute/path/to/your/module', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PIL', '/usr/lib/python2.7/dist-packages/gst-0.10', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client', '/usr/lib/python2.7/dist-packages/ubuntuone-client', '/usr/lib/python2.7/dist-packages/ubuntuone-control-panel', '/usr/lib/python2.7/dist-packages/ubuntuone-couch', '/usr/lib/python2.7/dist-packages/ubuntuone-installer', '/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol']
只需执行简单的操作,即可从其他文件夹导入.py文件。
假设您有一个目录,如:
lib/abc.py
然后在lib文件夹中保留一个空文件
__init__.py
然后使用
from lib.abc import <Your Module name>
在导入模块层次结构的每个文件夹中保留__init__.py文件。
这同样有效,而且比使用sys模块简单得多:
with open("C:/yourpath/foobar.py") as f:
eval(f.read())
我对python没有经验,所以如果我的话有任何错误,请告诉我。如果您的文件层次结构是这样安排的:
project\
module_1.py
module_2.py
module_1.py定义了一个名为func_1()的函数,module_2.py:
from module_1 import func_1
def func_2():
func_1()
if __name__ == '__main__':
func_2()
如果在cmd中运行python module_2.py,它将运行func1()定义的内容。这通常是我们导入相同层次结构文件的方式。但当您从module_2.py中的.module_1 import func_1写入时,python解释器将显示No module named'__main__.module_1';'__main__'不是包。因此,为了解决这个问题,我们只需保留刚才所做的更改,并将两个模块移动到一个包中,然后将第三个模块作为调用方运行module_2.py。
project\
package_1\
module_1.py
module_2.py
main.py
main.py:
from package_1.module_2 import func_2
def func_3():
func_2()
if __name__ == '__main__':
func_3()
但我们添加一个。在module_2.py中的module_1之前,如果我们不这样做并运行main.py,python解释器会说没有名为“module_1”的模块,这有点棘手,module_1.py就在module_.py旁边。现在我让module_1.y中的func_1()做一些事情:
def func_1():
print(__name__)
__name__记录谁调用func_1。现在我们保留。在module1之前,运行main.py,它将打印package1.module1,而不是module1。它表示调用func_1()的人与main.py位于同一层次结构中。暗示module1与module2.py本身处于同一层次结构。因此,如果没有点,main.py将在与自身相同的层次结构中识别模块_1,它可以识别package_1,但不能识别其下的内容。
现在让我们把它弄得有点复杂。您有一个config.ini,一个模块定义了一个函数,以便在与“main.py”相同的层次结构中读取它。
project\
package_1\
module_1.py
module_2.py
config.py
config.ini
main.py
由于某些不可避免的原因,您必须使用module_2.py调用它,因此它必须从上层导入module_2.py:
import ..config
pass
两个点表示从上层导入(三个点访问上层,而不是上层,依此类推)。现在我们运行main.py,解释器会说:ValueError:试图在顶级包之外进行相对导入。这里的“顶级包”是main.py。正因为config.py在main.py的旁边,所以它们处于相同的层次结构中,config.py不是“在”main.py之下,或者它不是由main.py“引导”的,所以它超出了main.py之外。要解决这个问题,最简单的方法是:
project\
package_1\
module_1.py
module_2.py
config.py
config.ini
main.py
我认为这符合排列项目文件层次结构的原则,您应该在不同的文件夹中排列具有不同功能的模块,只需在外部保留一个顶级调用程序,您就可以随意导入。
相对sys.path示例:
# /lib/my_module.py
# /src/test.py
if __name__ == '__main__' and __package__ is None:
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../lib')))
import my_module
基于这个答案。