How to properly use relative or absolute imports in Python modules?
在python中使用相对导入有一个缺点,您将不能再以标准方式运行模块,因为您将得到一个异常:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # /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 |
我应该如何修改样本代码才能执行全部:
我正在寻找一个能与Python2.6+协同工作的解决方案(包括3.x)。
您可以用一种不同的方式开始"以标准方式运行模块":
而不是:
1 | python foo/bar.py |
用途:
1 | python -mfoo.bar |
当然,
另外,请注意,在
更新:将其用作
1 | #!/usr/bin/python -mfoo.bar |
然后您可以直接在POSIX系统中执行该脚本。
首先,我假设您认识到您所写的将导致循环导入问题,因为foo导入bar和viceversa;尝试添加
1 | from foo import bar |
去测试.py,你会发现它失败了。必须更改示例才能工作。
所以,当相对导入失败时,您真正要求的是回退到绝对导入;事实上,如果您将foo.py或bar.py作为主模块执行,其他模块将仅位于根级别,如果它们与系统上的另一个模块共享名称,那么将选择哪个模块取决于sys.path中的顺序。由于当前目录通常是第一个,本地模块将被选中(如果可用),也就是说,如果在当前工作目录中有一个"os.py"文件,它将被选中而不是内置的。
一个可能的建议是:
P.Py
1 2 3 4 5 6 7 | try: from . import bar except ValueError: import bar if __name__ =="__main__": pass |
bar.py:
1 2 | if __name__ =="__main__": pass |
从适当的位置调用脚本通常会更好。
1 | python -m foo.bar |
可能是最好的方式。这将以脚本的形式运行模块。
每个文件夹中都需要
相对导入仅在执行以下操作时有效:
1 | python test.py |
test.py导入foo.py和foo.py可以相对导入test.py及以上文件夹中的任何内容。
你不能这样做:
1 2 3 | cd foo python foo.py python bar.py |
它永远不会起作用。
您可以尝试sys.path.append或sys.path.insert解决方案,但是您会弄乱路径,并且您会遇到f=open(文件名)的问题。
丢弃相对导入:无论如何,您应该将包名称空间视为全局名称空间。
要使这一点更受欢迎的诀窍是适当地编辑
1 2 3 | # one directory up _root_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) sys.path.insert(0, _root_dir)for now |
为什么不把"main"放在另一个.py文件中呢?
到目前为止,我找到的唯一解决方案是根本不使用相对进口。
由于当前的限制,我想知道什么时候应该有人在Python中使用相对导入。
在我使用的所有配置中,