Python 包内相对导入不在路径中
我想知道怎么在一个Python包中,从一个父目录导入一个文件到一个子目录里的文件,前提是这个父目录不在路径上。
因为我对Python打包的术语不是很清楚,所以我举个例子:
dir1/
__init__.py
runner.py
in_dir1.py
dir2/
__init__.py
in_dir2.py
dir1/in_dir1.py:
def example():
print "Hello from dir1/in_dir1.example()"
dir1/dir2/in_dir2.py
import in_dir1 #or whatever this should be to make this work
print "Inside in_dir2.py, calling in_dir1.example()"
print in_dir1.example()
假设dir1
不在Python的路径上,我想找到最好的方法把in_dir1
导入到in_dir2
中。
我试过用from .. import in_dir1
和from ..dir1 import in_dir1
,参考了这个问答,但都不行。正确的做法是什么呢?这个问答似乎有答案,但我不太明白该怎么用它来解决我的问题,特别是关于PEP 366的部分。
两个__init__.py
文件都是空的,我现在用的是v2.6。
我想在不使用Google上找到的任何路径技巧的情况下做到这一点。
2 个回答
你可以这样做:
import sys
sys.path.append('..')
这样是可以运行的。但别这么做,这可能会影响到其他模块。
我想你可以在导入后直接把它去掉,但也别这么做。
编辑:
其实,这样做也是可以的,我觉得这样做没有不安全的理由:
在in_dir2.py里面你可以这样写:
import sys
import os
current_module = sys.modules[__name__]
indir2file=current_module.__file__
sys.path.append(os.path.dirname(os.path.abspath(indir2file))+os.sep+".."+os.sep)
import in_dir1
尽量努力重构你的代码吧。
答案在你给的链接里:
相对导入是通过模块的
__name__
属性来判断这个模块在包中的位置。如果模块的名字没有包含任何包的信息(比如它被设置为 main),那么相对导入就会被当作这个模块是一个顶级模块来处理,不管这个模块在文件系统中的实际位置在哪里。
在 __main__
脚本中,你不能使用相对导入(也就是说,如果你直接运行 python in_dir2.py
)。
为了解决这个问题,PEP 366 允许你设置全局的 __package__
:
import dir1
if __name__ == '__main__':
__package__ = 'dir1.dir2'
from .. import in_dir1
注意,包 dir1
仍然必须在 sys.path
中!你可以通过修改 sys.path
来实现这一点。但是到那时,你和绝对导入相比又有什么不同呢?