我的项目结构如下:
$ tree .
.
├── pyproject.toml
└── src
└── project
├── __init__.py
├── main.py
└── module.py
$ cat pyproject.toml
[project]
name = "project"
version = "0.1"
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[project.scripts]
launcher = "project.main:main"
[tool.setuptools.packages.find]
where = ["src"]
$ cat src/project/main.py
#!/usr/bin/env python
import module
def main():
module.function()
if __name__ == "__main__":
main()
出于测试目的
module.function()
仅打印“Hello world!”。 main.py
是可执行的,所以我可以直接运行它,但大多数时候我使用vscode中的“播放”按钮。当我使用 pip install .
安装项目并尝试使用入口点时,问题就开始了:
$ launcher
Traceback (most recent call last):
File "/some/path/project/.venv/bin/launcher", line 5, in <module>
from project.main import main
File "/some/path/project/.venv/lib/python3.12/site-packages/project/main.py", line 3, in <module>
import module
ModuleNotFoundError: No module named 'module'
当我将导入行更改为
from project import module
时,我可以使用启动器,并且可以直接运行脚本,但仅当安装了软件包时。否则会出现错误:
$ src/project/main.py
Traceback (most recent call last):
File "/some/path/project/src/project/main.py", line 3, in <module>
from project import module
ModuleNotFoundError: No module named 'project'
问题是我应该如何导入
module.py
,以便我可以在安装或未安装时使用启动器直接运行它。
我应该在 pyproject.toml
中配置它,以便生成的启动器脚本可以与简单的 import module
一起使用吗?
或者可能在 __init__.py
中,因为如果不能正确初始化包,这个文件是做什么用的?
我想了解打包过程,并在 setuptools 文档中查找一些提示,但没有找到任何相关内容。
我也尝试过相对导入
from . import module
,但这仅在使用启动器运行时有效,而不是直接运行:
$ src/project/main.py
Traceback (most recent call last):
File "/some/path/project/src/project/main.py", line 3, in <module>
from . import module
ImportError: attempted relative import with no known parent package
最后我让它在这两种情况下都能工作:
import sys
import os
sys.path.append(os.path.dirname(__file__))
import module
但在我看来,这就像一个丑陋的黑客来搞乱
sys.path
,并且它需要其他可能不必要的导入。我正在寻找解决问题的好方法和推荐方法。
# module.py
def function():
print("Hello world!")
run.py
# run.py
from project.main import main
if __name__ == "__main__":
main()
main.py
# main.py
from project import module
def main():
module.function()
if __name__ == "__main__":
main()
python3 src/run.py
Hello world!