Python 包内相对导入不在路径中

5 投票
2 回答
1922 浏览
提问于 2025-04-17 11:06

我想知道怎么在一个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_dir1from ..dir1 import in_dir1,参考了这个问答,但都不行。正确的做法是什么呢?这个问答似乎有答案,但我不太明白该怎么用它来解决我的问题,特别是关于PEP 366的部分。

两个__init__.py文件都是空的,我现在用的是v2.6

我想在不使用Google上找到的任何路径技巧的情况下做到这一点。

2 个回答

0

可以这样做:

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

尽量努力重构你的代码吧。

3

答案在你给的链接里:

相对导入是通过模块的 __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 来实现这一点。但是到那时,你和绝对导入相比又有什么不同呢?

撰写回答