如何以
bar.py
仍然能够导入 foo.py
的方式打包以下最小示例。最好不需要更改 python 代码,而是将 -m trend.bar
之类的内容传递到 pyinstaller
。
鉴于结构:
.
├── toast
│ └── foo.py # VARIABLE = 42
└── trend
└── bar.py
其中
bar.py
包含
from toast import foo
print(foo.VARIABLE)
我会像
python3 -m trend.bar
一样执行此操作,没有任何问题。
pyinstaller --additional-hooks-dir=. trend/bar.py
。导入失败。欢迎来到 python 导入的神奇世界!理解这一点的关键是理解 python 如何使用 $PYTHONPATH 查找模块和包,您可以在运行脚本时通过打印 sys.path 来查看。如果您将此示例放入 PyCharm 中,它将找到模块 toast/foo.py 并毫无问题地打印变量,因为 PyCharm 会“神奇地”将项目的根目录(当前不是包)添加到 sys.path 中。但是,如果您从终端甚至在另一个编辑器(例如 VSCode)中运行它,您将收到 ModuleNotFound 错误。在尝试访问 foo.VARIABLE 之前,通过导入 sys 并打印它,您可以清楚地看到 sys.path 中发生了什么:
import sys
print(f"{sys.path=}")
from toast import foo
print(foo.VARIABLE)
如果您想使用导入,就好像项目根目录始终是 sys.path 的一部分,您可以手动添加它:
import sys
sys.path.append("path/to/your_project")
print(f"{sys.path=}")
from toast import foo
print(foo.VARIABLE)
现在这段代码将按照您的意愿在终端中运行:
python trend/bar.py
但我建议使用 python 包(带有空的 init.py 文件)而不是使用“普通”目录。