使用pip安装包后如何使本地导入工作?

问题描述 投票:0回答:1

我的项目结构如下:

$ 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

,并且它需要其他可能不必要的导入。我正在寻找解决问题的好方法和推荐方法。

    

python python-3.x python-import importerror pyproject.toml
1个回答
0
投票
我的模块中没有你的代码,所以我模拟了一个:
  1. # module.py def function(): print("Hello world!")
在 src 文件夹中添加名为 
    run.py
  1. 的运行器脚本
    
    
  2. # run.py from project.main import main if __name__ == "__main__": main()
修复 
    main.py
  1. 以使用绝对导入:
    
    
  2. # main.py from project import module def main(): module.function() if __name__ == "__main__": main()
运行运行脚本
  1. python3 src/run.py Hello world!
	
© www.soinside.com 2019 - 2024. All rights reserved.