lex*_*ler 5 python packaging project-structure setuptools setup.py
我需要一些有关使用setuptools和find_packages功能的解释。\n我有一个这样的项目结构:
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 project_dir_1\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 module.py\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 my_project\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 cli.py\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 subdir1\n\xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 module.py\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 conf\n\xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 module.py\n\xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 params\n\xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 config.yml\n\xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 subdir2\n\xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 module.py\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 version.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 project_dir_2\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 subdir1\n\xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 module.py\n\xe2\x94\x82 \xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x82 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 README.md\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 requirements.txt\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 setup.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tests\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 test_main.py\nRun Code Online (Sandbox Code Playgroud)\n\n实际上,我的所有代码都在该my_project目录中,而且我还有两个附加目录project_dir_1,project_dir_2其中包含必要的外部模块,我应该在包代码和另一个项目代码中导入这些模块,该包将安装在 venv 中。 \n我有安装脚本像这样:
setup(\n name=\'my_project\',\n version=\'0.0.1\',\n description=\'Python library.\',\n license=\'license\',\n author=\'me\',\n author_email=\'my_email\',\n entry_points={\'console_scripts\': [\'my_project=my_project.cli:main\']},\n python_requires=\'>=3.7\',\n packages=find_packages(\n include=[\'my_project\', \'project_dir_1\', \'project_dir_2\', \'my_project.*\', \'project_dir_1.*\', \'project_dir_2.*\']\n ),\n install_requires=list(open(join(dirname(__file__), \'requirements.txt\')).read().split()),\n)\nRun Code Online (Sandbox Code Playgroud)\n\n当我在另一个项目文件夹中激活 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这也是必要的。另外,当我从 shell 寻址运行my_project到 cli 时,出现错误:
Traceback (most recent call last):\n File "/home/developer/another_project/env/bin/my_project", line 11, in <module>\n load_entry_point(\'my_project==0.0.1\', \'console_scripts\', \'my_project\')()\n File "/home/developer/another_project/env/lib/python3.8/site-packages/pkg_resources/__init__.py", line 489, in load_entry_point\n return get_distribution(dist).load_entry_point(group, name)\n File "/home/developer/another_project/env/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2852, in load_entry_point\n return ep.load()\n File "/home/developer/another_project/env/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2443, in load\n return self.resolve()\n File "/home/developer/another_project/env/lib/python3.8/site-packages/pkg_resources/__init__.py", line 2449, in resolve\n module = __import__(self.module_name, fromlist=[\'__name__\'], level=0)\nModuleNotFoundError: No module named \'my_project\'\nRun Code Online (Sandbox Code Playgroud)\n\n那么组织这个复杂的项目结构并包含所有必要的代码setup.py以setuptools正确安装软件包的正确方法是什么?我需要对 python 项目打包有一些更好的理解,但仍然没有从寻找文档中得到这种情况的答案。
find_packages将解析相对于当前工作目录的路径,因此在项目根目录之外调用它将有效地安装任何内容(检查您是否看到通过例如运行安装的任何源
$ pip show -f my_project
Run Code Online (Sandbox Code Playgroud)
,我打赌什么都不会列出)。您必须在安装脚本中强制切换到项目根目录,例如在安装脚本中添加一条魔术线:
# 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(...)
Run Code Online (Sandbox Code Playgroud)