python 2.5中的相对导入
我知道Python中同样的导入问题有很多问题,但似乎没有人能够提供正确使用的清晰示例 假设我们有一个包python 2.5中的相对导入,python,import,relative-path,python-2.5,Python,Import,Relative Path,Python 2.5,我知道Python中同样的导入问题有很多问题,但似乎没有人能够提供正确使用的清晰示例 假设我们有一个包mypackage,包含两个模块foo和bar。在foo内部,我们需要能够访问bar 因为我们还在开发它,mypackage不在sys.path中 我们希望能够: 导入mypackage.foo 将foo.py作为脚本运行,并从\uuuuu main\uuuu部分执行示例用法或测试 使用Python 2.5 我们必须如何在foo.py中进行导入,以确保它在所有这些情况下都能工作 # mypa
mypackage
,包含两个模块foo
和bar
。在foo
内部,我们需要能够访问bar
因为我们还在开发它,mypackage
不在sys.path
中
我们希望能够:
- 导入
mypackage.foo
- 将
作为脚本运行,并从foo.py
部分执行示例用法或测试\uuuuu main\uuuu
- 使用Python 2.5
# 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()
请查看以下信息: 相对导入使用模块的
\uuuuu name\uuuu
属性来确定该模块在包层次结构中的位置。如果模块名称不包含任何程序包信息(例如,将其设置为“\uuuuu main\uuuuuu”
),则将解析相对导入,就像模块是顶级模块一样,而不考虑模块在文件系统上的实际位置
当您以脚本形式运行foo.py
时,该模块的\uuuuu name\uuuuuuu
是'\uuuuu main\uuuuuu'
,因此您无法进行相对导入。即使mypackage
在sys.path
上,这也是正确的。基本上,如果模块已导入,则只能从该模块进行相对导入
以下是解决此问题的几个选项:
1) 在foo.py
中,检查\uuuu name\uuuu=='\uuuuu main\uuuuu'
,并有条件地将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) 始终使用mypackage导入栏中的导入条
,并执行foo.py
,使mypackage
自动可见:
$ cd <path containing mypackage>
$ python -m mypackage.foo.foo
$cd
$python-m mypackage.foo.foo
我的解决方案看起来更干净,可以与所有其他导入一起位于顶部:
try:
from foo import FooClass
except ModuleNotFoundError:
from .foo import FooClass
我认为您必须区分可导入模块和脚本。我不确定我是否同意这种设计,但这是我对它的理解。通常,当您需要从上层导入软件包时,您会出错:您是否希望将bar
用作库而不是mypackage的子模块?也就是说,您能否将mypackage重构为mypackage1和mypackage2,其中mypackage2(带foo)导入mypackage1(带bar)?谢谢!唯一尚不清楚的是对包路径的检测。我明天会检查并返回结果。@sorin-我刚刚编辑了我的答案,因此无论从何处调用foo.py,您都可以获得mypackage的路径。在Windows上,我发现很少有getcwd()
不提供脚本目录的情况。至少有3种方法可以调用python脚本:“python a.py”、“a.py”,并从Windows资源管理器(最终通过pythonw)@sorin运行-不幸的是,我只能在Linux上进行测试,我看到的行为是,\uuu file\uuuu
要么是绝对路径,要么是从os.getcwd()
到foo.py
的路径。在这两种情况下,foo\u dir
是指向包含foo.py
的目录的绝对路径。不确定如果Windows不是这样,它需要如何更改。@sorin-如果您需要从bar使用doBar
,您需要从mypackage.bar导入doBar,或者从mypackage导入bar使用,并将其命名为bar.doBar()
。谢谢您的回答!它确实帮了我很多忙!