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

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

下面是一个视觉表示:

dirFoo\
    Foo.py
    dirBar\
        Bar.py

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


当前回答

不修改脚本的最简单方法是设置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']

其他回答

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

解决方案:

我有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插入的条目之前插入的。

您还可以将子目录添加到Python路径中,以便将其作为普通脚本导入。

import sys
sys.path.insert(0, <path to dirFoo>)
import Bar

在本例中,要将Bar.py导入Foo.py,首先我会将这些文件夹转换为Python包,如下所示:

dirFoo\
    __init__.py
    Foo.py
    dirBar\
        __init__.py
        Bar.py

然后我会在Foo.py中这样做:

from .dirBar import Bar

如果我希望名字空间看起来像Bar.whatever,或者

from . import dirBar

如果我想要名称空间dirBar.Bar.whatever。如果您在dirBar包下有更多模块,则第二种情况非常有用。

Linux用户快速而肮脏的方式

如果您只是在修补,而不关心部署问题,则可以使用符号链接(假设您的文件系统支持该链接)使模块或包在请求模块的文件夹中直接可见。

ln -s (path)/module_name.py

or

ln -s (path)/package_name

注意:“模块”是扩展名为.py的任何文件,“包”是包含__init__.py文件(可以是空文件)的任何文件夹。从使用的角度来看,模块和包是相同的——都会根据import命令的请求公开其包含的“定义和语句”。

参见:http://docs.python.org/2/tutorial/modules.html

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

from dirBar.Bar import *

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