我知道在 Python 中有很多关于相同导入问题的问题,但似乎没有人设法提供正确用法的清晰示例。
假设我们有一个包含两个模块foo
和bar
的包mypackage
。在 foo
中,我们需要能够访问 bar
。
因为我们还在开发中,mypackage
不在sys.path
中。
我们希望能够:
- 导入
mypackage.foo
- 将
foo.py
作为脚本运行,并从__main__
部分执行示例用法或测试。 - 使用 Python 2.5
我们如何在 foo.py 中进行导入以确保它在所有这些情况下都能正常工作。
# mypackage/__init__.py
...
# mypackage/foo/__init__.py
...
# mypackage/bar.py
def doBar()
print("doBar")
# mypackage/foo/foo.py
import bar # fails with module not found
import .bar #fails due to ValueError: Attempted relative import in non-package
def doFoo():
print(doBar())
if __name__ == '__main__':
doFoo()
最佳答案
查看来自 PEP 328 的以下信息:
Relative imports use a module's
__name__
attribute to determine that module's position in the package hierarchy. If the module's name does not contain any package information (e.g. it is set to'__main__'
) then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.
当你运行 foo.py
作为脚本,该模块的 __name__
是'__main__'
,所以你不能做相对导入。即使 mypackage
也是如此在sys.path
.基本上,如果该模块已导入,您只能从该模块进行相对导入。
这里有几个解决这个问题的方法:
1) 在 foo.py
, 检查是否 __name__ == '__main__'
并有条件地添加 mypackage
至 sys.path
:
if __name__ == '__main__':
import os, sys
# get an absolute path to the directory that contains mypackage
foo_dir = os.path.dirname(os.path.join(os.getcwd(), __file__))
sys.path.append(os.path.normpath(os.path.join(foo_dir, '..', '..')))
from mypackage import bar
else:
from .. import bar
2) 始终导入 bar
使用 from mypackage import bar
, 并执行 foo.py
以这样的方式 mypackage
自动可见:
$ cd <path containing mypackage>
$ python -m mypackage.foo.foo
关于python - python 2.5 中的相对导入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8299270/