如何同时__main__包 -OR- 脚本和包子模块



我有这个结构:

app.py
sub/
    __init__.py
    lib.py
    utils.py

app.py,我希望能够像这样做:

from sub.lib import some_func

lib.py,我希望能够导入utils.py

我还希望可以直接将lib.py作为脚本执行。 cd sub; python3 lib.py .(

问题是,如果我lib.py作为脚本启动,它将不是一个包,因此,它不能使用相对导入,所以像from .utils import some_util_func这样的 sth 不起作用。但是,如果我将lib.py作为sub包的一部分导入,则只有相对导入才有效。

我该如何解决这个问题?(以简单的方式。 例如,无需创建另一个小包装器脚本只是为了调用lib.py

例如,如果有一种方法可以将__main__模块标记为包,它将解决这个问题。但是怎么做呢?这可能吗?例如,通过定义__path__左右?

您可以在启动程序时设置 PYTHONPATH 环境变量。

只需从 lib 目录键入:

PYTHNONPATH="path/to/root/directory" python lib.py
<</div> div class="one_answers">

好吧,实际上,我的最后一条评论确实有效。如果我在lib.py开头添加这个,它似乎有效:

import os
if __name__ == '__main__':
    __path__ = [os.path.dirname(os.path.abspath(__file__))]

(关于__path__,请参阅此处。

使用较新的 Python 版本 (3.9( 进行编辑,这似乎已经不够了。有关扩展版本,请参见下文。

<小时 />

此外,在 PEP 366 中还提到了:

当主模块由其文件名指定时,__package__属性将设置为 None 。若要在直接执行模块时允许相对导入,在第一个相对导入语句之前需要类似于以下内容的样板:

if __name__ == "__main__" and __package__ is None:
    __package__ = "expected.package.name"

我还没有尝试过这个。

<小时 />

对于 Python 3.9,我需要扩展我的解决方案:

if __name__ == '__main__':
    # Make relative imports work here. https://stackoverflow.com/questions/54576879/
    __path__ = [os.path.dirname(os.path.abspath(__file__))]
    __package__ = "YOUR_CUSTOM_PACKAGE_NAME"
    pkg_mod = types.ModuleType(__package__)
    sys.modules[__package__] = pkg_mod
    pkg_mod.__package__ = __package__
    pkg_mod.__file__ = os.path.abspath("__init__.py")
    pkg_mod.__path__ = __path__

最新更新