多个 main 的正确 python 导入

Chr*_*oph 5 python import module

我有以下文件结构

\n\n
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 test.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 sub\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 foo.py\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 bar.py\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用测试.py:

\n\n
# test.py\nfrom sub import foo\nfoo.test()\n
Run Code Online (Sandbox Code Playgroud)\n\n

和 foo.py:

\n\n
# foo.py\nfrom . import bar\n\ndef test():\n  bar.test()\n
Run Code Online (Sandbox Code Playgroud)\n\n

和 bar.py:

\n\n
# bar.py\ndef test():\n  print(\'This is a test\')\n
Run Code Online (Sandbox Code Playgroud)\n\n

从命令行调用 test.py 时效果很好。

\n\n
home/$ python test.py\nThis is a test\n
Run Code Online (Sandbox Code Playgroud)\n\n

现在我希望能够直接从命令行调用 foo.py 。所以我将 foo.py 更改为:

\n\n
# foo.py\nfrom . import bar\n\ndef test():\n  bar.test()\n\nif __name__ == \'__main__\':\n  test()\n
Run Code Online (Sandbox Code Playgroud)\n\n

但是当我调用它时它不起作用

\n\n
/home$ cd sub\n/home/sub$ python bar.py\nTraceback (most recent call last):\n  File "foo.py", line 1, in <module>\n    from . import bar\nImportError: cannot import name \'bar\' from \'__main__\' (foo.py)\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是有道理的,因为 python 文档指出

\n\n
\n

请注意,相对导入基于当前模块的名称。由于主模块的名称始终为“__main__”,因此用作 Python 应用程序主模块的模块必须始终使用绝对导入。

\n
\n\n

所以我可以将 foo.py 中的 import 语句更改为

\n\n
# foo.py\nimport bar\n
Run Code Online (Sandbox Code Playgroud)\n\n

但随后调用 test.py 就不再起作用了。

\n\n
/home$ python test.py\nTraceback (most recent call last):\n  File "test.py", line 1, in <module>\n    from sub import foo\n  File "/home/chr/code/import/sub/foo.py", line 1, in <module>\n    import bar\nModuleNotFoundError: No module named \'bar\'\n
Run Code Online (Sandbox Code Playgroud)\n\n

有什么办法可以解决这个问题,或者根本不可能使用来自两个不同电源的 bar.py 吗?

\n\n

编辑:一种解决方案可能是

\n\n
if __name__ == \'__main__\':\n    import bar\nelse:\n    from . import bar\n
Run Code Online (Sandbox Code Playgroud)\n\n

但这看起来很丑

\n

Dip*_*ami 1

您在问题中提供的解决方案绝对是其中之一。

\n\n

恐怕我提供的其他解决方案也不太好。但由于这是另一个解决方案,我正在写一个答案。

\n\n

进行这几个更改,它应该会起作用。

\n\n
# bar.py\nimport bar  # use an absolute import\n\ndef test():\n  bar.test()\n\nif __name__ == '__main__':\n  test()\n
Run Code Online (Sandbox Code Playgroud)\n\n

将这两行添加到test.py. 添加路径sys.path将使该位置(模块)可用于导入。之后您只需导入该模块即可。

\n\n
import sys\nsys.path.append('./sub')\n\nimport foo\n\nfoo.test()\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是我的结构,和你的一样。

\n\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 sub\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 bar.py\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 foo.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 test.py\n
Run Code Online (Sandbox Code Playgroud)\n\n

运行这两个文件都可以。

\n\n
$ python3 test.py \nThis is a test\n$ python3 sub/foo.py \nThis is a test\n
Run Code Online (Sandbox Code Playgroud)\n