使用pip安装pyproject.toml依赖失败的问题排查与解决
从Poetry迁移到PEP 621规范的pyproject.toml问题解决
背景
我有一个用Poetry创建的旧项目,自动生成的pyproject.toml配置如下:
[tool.poetry] name = "Dota2Learning" version = "0.3.0" description = "Statistics and Machine Learning for your Dota2 Games." license = "MIT" readme = "README.md" homepage = "Coming soon..." repository = "https://github.com/drigols/dota2learning/" documentation = "Coming soon..." include = ["CHANGELOG.md"] authors = [ "drigols <drigols.creative@gmail.com>", ] maintainers = [ "drigols <drigols.creative@gmail.com>", ] keywords = [ "dota2", "statistics", "machine Learning", "deep learning", ] [tool.poetry.scripts] dota2learning = "dota2learning.cli.main:app" [tool.poetry.dependencies] python = "^3.10" requests = "^2.27.1" typer = {extras = ["all"], version = "^0.4.1"} install = "^1.3.5" SQLAlchemy = "^1.4.39" PyMySQL = "^1.0.2" cryptography = "^37.0.4" pydantic = "^1.9.1" rich = "^12.5.1" fastapi = "^0.79.0" uvicorn = "^0.18.2" [tool.poetry.dev-dependencies] black = {extras = ["jupyter"], version = "^22.3.0"} pre-commit = "^2.19.0" flake8 = "^4.0.1" reorder-python-imports = "^3.1.0" pyupgrade = "^2.34.0" coverage = "^6.4.1" [tool.black] line-length = 79 include = '\.pyi?$' # All Python files exclude = ''' /(\n \.git\n | \.hg\n | \.mypy_cache\n | \.tox\n | \.venv\n | _build\n | buck-out\n | build\n | dist\n)/ ''' [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" [tool.poetry.urls] "Bug Tracker" = "https://github.com/drigols/dota2learning/issues"
之前执行pip install .可以正常安装,但我想脱离Poetry,改用符合PEP 621规范的方式管理项目和依赖,于是手动编写了新的pyproject.toml:
[project] name = "Dota2Learning" version = "2.0.0" description = "Statistics and Machine Learning for your Dota2 Games." license = "MIT" readme = "README.md" homepage = "" requires-python = ">=3.10" repository = "https://github.com/drigols/dota2learning/" documentation = "" include = ["CHANGELOG.md"] authors = [ "drigols <drigols.creative@gmail.com>", ] maintainers = [ "drigols <drigols.creative@gmail.com>", ] keywords = [ "dota2", "statistics", "machine Learning", "deep learning", ] dependencies = [ "requests>=2.27.1", "typer>=0.4.1", "SQLAlchemy>=1.4.39", "PyMySQL>=1.0.2", "cryptography>=37.0.4", "pydantic>=1.9.1", "rich>=12.5.1", "fastapi>=0.79.0", "uvicorn>=0.18.2", ] [project.optional-dependencies] # Dev dependencies. dev = [ "black>=22.3.0", "pre-commit>=2.19.0", "flake8>=4.0.1", "reorder-python-imports>=3.1.0", "pyupgrade>=2.34.0", ] # Testing dependencies. test = [ "coverage>=6.4.1", ] # Docs dependencies. doc = [] [project.scripts] dota2learning = "dota2learning.cli.main:app" [tool.black] line-length = 79 include = '\.pyi?$' # All Python files exclude = ''' /(\n \.git\n | \.hg\n | \.mypy_cache\n | \.tox\n | \.venv\n | _build\n | buck-out\n | build\n | dist\n)/ '''
报错信息
执行pip install .时失败,报错如下:
Installing build dependencies ... done Getting requirements to build wheel ... error error: subprocess-exited-with-error × Getting requirements to build wheel did not run successfully. │ exit code: 1 ╰─> [89 lines of output] configuration error: `project.license` must be valid exactly by one definition (2 matches found): - keys: 'file': {type: string} required: ['file'] - keys: 'text': {type: string} required: ['text'] DESCRIPTION: `Project license <https://www.python.org/dev/peps/pep-0621/#license>`_. GIVEN VALUE: "MIT" OFFENDING RULE: 'oneOf' DEFINITION: { "oneOf": [ { "properties": { "file": { "type": "string", "$$description": [ "Relative path to the file (UTF-8) which contains the license for the", "project." ] } }, "required": [ "file" ] }, { "properties": { "text": { "type": "string", "$$description": [ "The license of the project whose meaning is that of the", "`License field from the core metadata", "<https://packaging.python.org/specifications/core-metadata/#license>`_." ] } }, "required": [ "text" ] } ] } Traceback (most recent call last): File "/home/drigols/Workspace/dota2learning/environment/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 351, in <module> main() File "/home/drigols/Workspace/dota2learning/environment/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 333, in main json_out['return_val'] = hook(**hook_input['kwargs']) File "/home/drigols/Workspace/dota2learning/environment/lib/python3.10/site-packages/pip/_vendor/pep517/in_process/_in_process.py", line 118, in get_requires_for_build_wheel return hook(config_settings) File "/tmp/pip-build-env-up7_m__d/overlay/lib/python3.10/site-packages/setuptools/build_meta.py", line 338, in get_requires_for_build_wheel return self._get_build_requires(config_settings, requirements=['wheel']) File "/tmp/pip-build-env-up7_m__d/overlay/lib/python3.10/site-packages/setuptools/build_meta.py", line 320, in _get_build_requires self.run_setup() File "/tmp/pip-build-env-up7_m__d/overlay/lib/python3.10/site-packages/setuptools/build_meta.py", line 484, in run_setup super(_BuildMetaLegacyBackend, File "/tmp/pip-build-env-up7_m__d/overlay/lib/python3.10/site-packages/setuptools/build_meta.py", line 335, in run_setup exec(code, locals()) File "<string>", line 1, in <module> File "/tmp/pip-build-env-up7_m__d/overlay/lib/python3.10/site-packages/setuptools/__init__.py", line 87, in setup return distutils.core.setup(**attrs) File "/tmp/pip-build-env-up7_m__d/overlay/lib/python3.10/site-packages/setuptools/_distutils/core.py", line 159, in setup dist.parse_config_files() File "/tmp/pip-build-env-up7_m__d/overlay/lib/python3.10/site-packages/setuptools/dist.py", line 867, in parse_config_files pyprojecttoml.apply_configuration(self, filename, ignore_option_errors) File "/tmp/pip-build-env-up7_m__d/overlay/lib/python3.10/site-packages/setuptools/config/pyprojecttoml.py", line 62, in apply_configuration config = read_configuration(filepath, True, ignore_option_errors, dist) File "/tmp/pip-build-env-up7_m__d/overlay/lib/python3.10/site-packages/setuptools/config/pyprojecttoml.py", line 126, in read_configuration validate(subset, filepath) File "/tmp/pip-build-env-up7_m__d/overlay/lib/python3.10/site-packages/setuptools/config/pyprojecttoml.py", line 51, in validate raise ValueError(f"{error}\n{summary}") from None ValueError: invalid pyproject.toml config: `project.license`. configuration error: `project.license` must be valid exactly by one definition (2 matches found): - keys: 'file': {type: string} required: ['file'] - keys: 'text': {type: string} required: ['text'] [end of output] note: This error originates from a subprocess, and is likely not a problem with pip. error: subprocess-exited-with-error × Getting requirements to build wheel did not run successfully. │ exit code: 1 ╰─> See above for output. note: This error originates from a subprocess, and is likely not a problem with pip.
解决方法
修改后的pyproject.toml如下:
[build-system] # Minimum requirements for the build system to execute. requires = ["setuptools", "wheel"] # PEP 508 specifications. build-backend = "setuptools.build_meta" # Ignore flat-layout. [tool.setuptools] py-modules = [] [project] name = "Dota2Learning" version = "2.0.0" description = "Statistics and Machine Learning for your Dota2 Games." license = {file = "LICENSE.md"} readme = "README.md" requires-python = ">=3.10.0" authors = [ { name = "Rodrigo Leite", email = "drigols.creative@gmail.com" }, ] maintainers = [ { name = "Rodrigo Leite", email = "drigols.creative@gmail.com" }, ] keywords = [ "dota2", "statistics", "machine Learning", "deep learning", ] dependencies = [ "requests>=2.27.1", "typer>=0.4.1", "SQLAlchemy>=1.4.39", "PyMySQL>=1.0.2", "cryptography>=37.0.4", "pydantic>=1.9.1", "rich>=12.5.1", "fastapi>=0.79.0", "uvicorn>=0.18.2", ] [project.optional-dependencies] # Dev dependencies. dev = [ "black>=22.3.0", "pre-commit>=2.19.0", "flake8>=4.0.1", "reorder-python-imports>=3.1.0", "pyupgrade>=2.34.0", ] # Test dependencies. test = [ "coverage>=6.4.1", ] # Doc dependencies. doc = [] [project.scripts] # dota2learning = "dota2learning.cli.main:app" [tool.black] line-length = 79 include = '\.pyi?$' # All Python files exclude = ''' /(\n \.git\n | \.hg\n | \.mypy_cache\n | \.tox\n | \.venv\n | _build\n | buck-out\n | build\n | dist\n)/ '''
关键修复点
project.license字段修正:PEP 621规范要求license必须是字典格式,要么用{file = "LICENSE.md"}指定许可证文件,要么用{text = "MIT"}直接写许可证文本,不能直接使用字符串"MIT"。- 添加构建系统配置:新增
[build-system]部分,指定使用setuptools和wheel作为构建后端,确保pip能正确处理项目构建。 - 作者/维护者格式调整:将
authors和maintainers从字符串格式改为字典格式{name = "...", email = "..."},符合PEP 621的规范要求。 - 添加setuptools工具配置:新增
[tool.setuptools]并设置py-modules = [],避免flat-layout导致的识别问题。
内容的提问来源于stack exchange,提问作者drigols
相关产品推荐
相关产品推荐

