关于使用setuptools
和find_packages
功能,我需要一些解释。我有一个这样的项目结构:
├── project_dir_1
│ ├── module.py
│ ├── __init__.py
├── my_project
│ ├── cli.py
│ ├── subdir1
│ │ ├── __init__.py
│ │ ├── module.py
│ ├── conf
│ │ ├── module.py
│ │ ├── params
│ │ │ ├── config.yml
│ │ ├── __init__.py
│ ├── subdir2
│ │ ├── module.py
│ ├── __init__.py
│ └── version.py
├── project_dir_2
│ ├── subdir1
│ │ ├── module.py
│ │ ├── __init__.py
│ ├── __init__.py
├── README.md
├── requirements.txt
├── setup.py
└── tests
└── test_main.py
实际上我在my_project
目录中的所有代码,而且我还有两个附加目录project_dir_1
和project_dir_2
,其中包含必要的外部模块,我应该从此处导入程序包代码以及该程序包中的其他项目代码将安装在venv中。我有这样的安装脚本:
setup(
name='my_project',
version='0.0.1',
description='Python library.',
license='license',
author='me',
author_email='my_email',
entry_points={'console_scripts': ['my_project=my_project.cli:main']},
python_requires='>=3.7',
packages=find_packages(
include=['my_project', 'project_dir_1', 'project_dir_2', 'my_project.*', 'project_dir_1.*', 'project_dir_2.*']
),
install_requires=list(open(join(dirname(__file__), 'requirements.txt')).read().split()),
)
[当我在另一个项目文件夹中激活venv并尝试从软件包根目录文件夹(如python ..\package_root\setup.py install
)安装软件包时,在安装过程中一切正常。 pip list
显示所有依赖项,my_project 0.0.1
。但是,如果我尝试使用venv解释器从my_project导入某些内容,则会出现错误:ModuleNotFoundError: No module named 'my_project'
。如果我尝试导入类似from project_dir_1 import module
的东西,则同样的结果也是必须的。另外,当我只从外壳寻址到cli运行my_project
时,我得到一个错误:
Traceback (most recent call last):
File "/home/developer/another_project/env/bin/my_project", line 11, in <module>
load_entry_point('my_project==0.0.1', 'console_scripts', 'my_project')()
File "/home/developer/another_project/env/lib/python3.8/site-packages/pkg_resources/__init__.py", line 489, in load_entry_point
return get_distribution(dist).load_entry_point(group, name)
File "/home/developer/another_project/env/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2852, in load_entry_point
return ep.load()
File "/home/developer/another_project/env/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2443, in load
return self.resolve()
File "/home/developer/another_project/env/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2449, in resolve
module = __import__(self.module_name, fromlist=['__name__'], level=0)
ModuleNotFoundError: No module named 'my_project'
那么,什么是正确的方法来组织这个复杂的项目结构,并在setup.py
中包含所有必需的代码,以使setuptools
正确安装软件包?我需要对python项目包装有更好的了解,但仍然无法通过搜索文档获得这种情况的答案。
[find_packages
将解析相对于当前工作目录的路径,因此在项目根目录之外调用它不会有效地安装任何内容(检查您是否看到例如通过运行安装的任何源代码
$ pip show -f my_project
,我敢打赌不会列出任何东西)。您必须在设置脚本中强制切换到项目根目录,例如在您的设置脚本中添加一条魔术线:
# setup.py
import os
from setuptools import setup
# old-style for python 2
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
# new style for python 3
from pathlib import Path
os.chdir(Path(__file__).parent.absolute())
setup(...)