我有这个结构:
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__