如何在Python模块中正确使用相对或绝对导入? [英] How to properly use relative or absolute imports in Python modules?
问题描述
在Python中使用相对导入有一个缺点,您将无法再以独立方式运行模块,因为您将得到异常:ValueError: Attempted relative import in non-package
# /test.py: just a sample file importing foo module
import foo
...
# /foo/foo.py:
from . import bar
...
if __name__ == "__main__":
pass
# /foo/bar.py: a submodule of foo, used by foo.py
from . import foo
...
if __name__ == "__main__":
pass
我应该如何修改示例代码才能执行所有内容:test.py
,foo.py
和bar.py
我正在寻找一种适用于python 2.6+(包括3.x)的解决方案.
首先,我假设您意识到您编写的内容将导致循环导入问题,因为foo导入bar,反之亦然;尝试添加
from foo import bar
到test.py,您将看到它失败.必须更改示例才能正常工作.
因此,您要问的是,当相对导入失败时,回退到绝对导入.实际上,如果您将foo.py或bar.py作为主要模块执行,则其他模块将仅位于根级别,并且它们是否与系统上要选择的其他模块共享名称取决于该模块. sys.path中的顺序.由于当前目录通常是第一个,因此将选择本地模块(如果有)-即,如果当前工作目录中有一个"os.py"文件,则将选择它而不是内置目录.>
可能的建议是:
foo.py
try:
from . import bar
except ValueError:
import bar
if __name__ == "__main__":
pass
bar.py:
if __name__ == "__main__":
pass
从正确的位置调用脚本通常会更好.
python -m foo.bar
可能是最好的方法.此将模块作为脚本运行.
Usage of relative imports in Python has one drawback, you will not be able to run the modules as standalones anymore because you will get an exception: ValueError: Attempted relative import in non-package
# /test.py: just a sample file importing foo module
import foo
...
# /foo/foo.py:
from . import bar
...
if __name__ == "__main__":
pass
# /foo/bar.py: a submodule of foo, used by foo.py
from . import foo
...
if __name__ == "__main__":
pass
How should I modify the sample code in order to be able to execute all: test.py
, foo.py
and bar.py
I'm looking for a solution that works with python 2.6+ (including 3.x).
First, I assume you realize what you've written would lead to a circular import issue, because foo imports bar and viceversa; try adding
from foo import bar
to test.py, and you'll see it fails. The example must be changed in order to work.
So, what you're asking is really to fallback to absolute import when relative import fails; in fact, if you're executing foo.py or bar.py as the main module, the other modules will just lie at the root level, and if they share the name with another module on the system which one will be picked depends on the order in sys.path. Since the current dir is usually the first, local modules will be picked if available - i.e., if you've got an 'os.py' file in the current working dir, it'll be picked instead of the builtin one.
A possibile suggestion is:
foo.py
try:
from . import bar
except ValueError:
import bar
if __name__ == "__main__":
pass
bar.py:
if __name__ == "__main__":
pass
By the way calling scripts from the proper position is usually way better.
python -m foo.bar
Is probably the best way to go. This runs the module as a script.
这篇关于如何在Python模块中正确使用相对或绝对导入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!