sor*_*rin 16 python import relative-path python-2.5
我知道有很多关于Python中相同导入问题的问题,但似乎没有人设法提供正确使用的明确示例.
比方说,我们有一个包mypackage
有两个模块foo
和bar
.在里面,foo
我们需要能够访问bar
.
因为我们还在开发它,mypackage
所以不在sys.path
.
我们希望能够:
mypackage.foo
foo.py
作为脚本运行并从该__main__
部分执行示例用法或测试.我们如何在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()
Run Code Online (Sandbox Code Playgroud)
And*_*ark 29
请查看PEP 328的以下信息:
相对导入使用模块的
__name__
属性来确定模块在包层次结构中的位置.如果模块的名称不包含任何包信息(例如,它设置为'__main__'
),则解析相对导入,就像模块是顶级模块一样,无论模块实际位于文件系统的哪个位置.
当您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
Run Code Online (Sandbox Code Playgroud)
2)始终导入bar
使用from mypackage import bar
,并foo.py
以mypackage
自动可见的方式执行:
$ cd <path containing mypackage>
$ python -m mypackage.foo.foo
Run Code Online (Sandbox Code Playgroud)
小智 7
我的解决方案看起来更干净一些,可以与所有其他进口产品一起放在顶部:
try:
from foo import FooClass
except ModuleNotFoundError:
from .foo import FooClass
Run Code Online (Sandbox Code Playgroud)