'extras_require' 必须是字典,其值是包含有效 project/version 要求说明符的字符串或字符串列表
'extras_require' must be a dictionary whose values are strings or lists of strings containing valid project/version requirement specifiers
我有一个 setup.py
,其中包含以下内容:
from pip._internal.req import parse_requirements
def load_requirements(fname):
"""Turn requirements.txt into a list"""
reqs = parse_requirements(fname, session="test")
return [str(ir.requirement) for ir in reqs]
setup(
name="Projectname",
[...]
python_requires='>=3.6',
extras_require={
'dev': load_requirements('./requirements/dev.txt')
},
install_requires=load_requirements('./requirements/prod.txt')
)
我的 ./requirements/prod.txt
看起来像这样:
-r common.txt
和我的 ./requirements/dev.txt
类似,但有一些特定于开发的包。我的 ./requirements/common.txt
包含一行,用于从 github link 中 pip 安装一个包,例如:
-e git://github.com/BioGeek/tta_wrapper.git@master#egg=tta_wrapper
但是,由于我添加了该行,命令 python setup.py build
失败并显示:
error in Projectname setup command: 'extras_require' must be a dictionary whose values are strings or lists of strings containing valid project/version requirement specifiers.
相关包的版本:
pip 20.2.2
setuptools 50.0.0
如何修改我的 setup.py
或我的需求文件来解决这个问题?
编辑
如 of Martijn Pieters 所示修改我的 setup.py
后,我可以确认 load_requirements
现在将我的需求文件变成一个列表,其中包含 name@ url 直接引用语法在需要的地方。
>>> load_requirements('./requirements/prod.txt')
['absl-py==0.8.1', 'GitPython==3.1.0', 'numpy==1.18.4', 'pip==20.2.2', 'protobuf==3.12.0', 'setuptools==41.0.0', 'scikit_learn==0.22', 'tensorflow_hub==0.8.0', 'importlib-metadata==1.6.1', 'keras-tuner==1.0.1', 'apache-beam==2.23.0', 'ml-metadata==0.23.0', 'pyarrow==0.17.0', 'tensorflow==2.3.0', 'tensorflow-data-validation==0.23.0', 'tensorflow-metadata==0.23.0', 'tensorflow-model-analysis==0.23.0', 'tensorflow-transform==0.23.0', 'tta_wrapper @ git://github.com/BioGeek/tta_wrapper.git@master']
但是,现在当我 运行 python setup.py build
:
时出现以下错误
$ python setup.py build
/home/biogeek/code/programname/env/lib/python3.6/site-packages/_distutils_hack/__init__.py:30: UserWarning: Setuptools is replacing distutils.
warnings.warn("Setuptools is replacing distutils.")
running build
Traceback (most recent call last):
File "setup.py", line 91, in <module>
install_requires=load_requirements('./requirements/prod.txt')
File "/home/biogeek/code/programname/env/lib/python3.6/site-packages/setuptools/__init__.py", line 153, in setup
return distutils.core.setup(**attrs)
File "/home/biogeek/code/programname/env/lib/python3.6/site-packages/setuptools/_distutils/core.py", line 148, in setup
dist.run_commands()
File "/home/biogeek/code/programname/env/lib/python3.6/site-packages/setuptools/_distutils/dist.py", line 967, in run_commands
self.run_command(cmd)
File "/home/biogeek/code/programname/env/lib/python3.6/site-packages/setuptools/_distutils/dist.py", line 984, in run_command
cmd_obj = self.get_command_obj(command)
File "/home/biogeek/code/programname/env/lib/python3.6/site-packages/setuptools/_distutils/dist.py", line 859, in get_command_obj
cmd_obj = self.command_obj[command] = klass(self)
File "/usr/lib/python3.6/distutils/cmd.py", line 57, in __init__
raise TypeError("dist must be a Distribution instance")
TypeError: dist must be a Distribution instance
编辑 2
我终于安装成功了。我尝试了一些东西,所以不完全确定最终是什么解决了这个问题,但是我:
- 已将
setuptools
从 50.0.0
降级为 41.0.0
- 将
setuptools
作为我的需求文件的第一行(参见 here)
- 添加了一个粗糙的、hacky 的一次性函数,以指向具有名称 @url 语法的 zip 存档。
def _format_requirement(req):
if str(req.requirement) == 'git://github.com/BioGeek/tta_wrapper.git@master#egg=tta_wrapper':
return 'tta_wrapper @ https://github.com/BioGeek/tta_wrapper/archive/v0.0.1.zip'
return str(req.requirement)
您只能使用PEP 508 - Dependency specification for Python Software Packages个要求。根据该标准,git://github.com/BioGeek/tta_wrapper.git@master#egg=tta_wrapper
不是有效语法。
setuptools
接受 name@ url
direct reference syntax:
tta_wrapper @ git://github.com/BioGeek/tta_wrapper.git
你不能把它放在 requirements.txt 文件中,但是 和 不能使用 -e
开关。后者只能取VCSURL或本地文件路径,不是需求规范;见 Requirements File Format section.
所以你在这里进行了格式转换。我会检查 parse_requirements()
生成的 ParsedRequirement
对象上的 is_editable
标志,并相应地改变行为。您必须将要求字符串解析为 URL,取出 #egg=
片段并将其放在前面:
from urllib.parse import urlparse
def _format_requirement(req):
if req.is_editable:
# parse out egg=... fragment from VCS URL
parsed = urlparse(req.requirement)
egg_name = parsed.fragment.partition("egg=")[-1]
without_fragment = parsed._replace(fragment="").geturl()
return f"{egg_name} @ {without_fragment}"
return req.requirement
def load_requirements(fname):
"""Turn requirements.txt into a list"""
reqs = parse_requirements(fname, session="test")
return [_format_requirement(ir) for ir in reqs]
上面然后把-e git:...#egg=tta_wrapper
变成tta_wrapper @ git:...
:
>>> load_requirements('./requirements/dev.txt')
['tta_wrapper @ git://github.com/BioGeek/tta_wrapper.git@master', 'black==20.08b1']
在我的情况下,我的要求中没有任何 github link,但是行
-r common.txt
在 ./requirements/prod.txt
中导致了同样的错误。
我添加了愚蠢的条件,现在对我有用了:
def load_requirements(filename) -> list:
requirements = []
try:
with open(filename) as req:
requirements = [line for line in req.readlines() if line.strip() != "-r common.txt"]
except Exception as e:
print(e)
return requirements
我有一个 setup.py
,其中包含以下内容:
from pip._internal.req import parse_requirements
def load_requirements(fname):
"""Turn requirements.txt into a list"""
reqs = parse_requirements(fname, session="test")
return [str(ir.requirement) for ir in reqs]
setup(
name="Projectname",
[...]
python_requires='>=3.6',
extras_require={
'dev': load_requirements('./requirements/dev.txt')
},
install_requires=load_requirements('./requirements/prod.txt')
)
我的 ./requirements/prod.txt
看起来像这样:
-r common.txt
和我的 ./requirements/dev.txt
类似,但有一些特定于开发的包。我的 ./requirements/common.txt
包含一行,用于从 github link 中 pip 安装一个包,例如:
-e git://github.com/BioGeek/tta_wrapper.git@master#egg=tta_wrapper
但是,由于我添加了该行,命令 python setup.py build
失败并显示:
error in Projectname setup command: 'extras_require' must be a dictionary whose values are strings or lists of strings containing valid project/version requirement specifiers.
相关包的版本:
pip 20.2.2
setuptools 50.0.0
如何修改我的 setup.py
或我的需求文件来解决这个问题?
编辑
如 setup.py
后,我可以确认 load_requirements
现在将我的需求文件变成一个列表,其中包含 name@ url 直接引用语法在需要的地方。
>>> load_requirements('./requirements/prod.txt')
['absl-py==0.8.1', 'GitPython==3.1.0', 'numpy==1.18.4', 'pip==20.2.2', 'protobuf==3.12.0', 'setuptools==41.0.0', 'scikit_learn==0.22', 'tensorflow_hub==0.8.0', 'importlib-metadata==1.6.1', 'keras-tuner==1.0.1', 'apache-beam==2.23.0', 'ml-metadata==0.23.0', 'pyarrow==0.17.0', 'tensorflow==2.3.0', 'tensorflow-data-validation==0.23.0', 'tensorflow-metadata==0.23.0', 'tensorflow-model-analysis==0.23.0', 'tensorflow-transform==0.23.0', 'tta_wrapper @ git://github.com/BioGeek/tta_wrapper.git@master']
但是,现在当我 运行 python setup.py build
:
$ python setup.py build
/home/biogeek/code/programname/env/lib/python3.6/site-packages/_distutils_hack/__init__.py:30: UserWarning: Setuptools is replacing distutils.
warnings.warn("Setuptools is replacing distutils.")
running build
Traceback (most recent call last):
File "setup.py", line 91, in <module>
install_requires=load_requirements('./requirements/prod.txt')
File "/home/biogeek/code/programname/env/lib/python3.6/site-packages/setuptools/__init__.py", line 153, in setup
return distutils.core.setup(**attrs)
File "/home/biogeek/code/programname/env/lib/python3.6/site-packages/setuptools/_distutils/core.py", line 148, in setup
dist.run_commands()
File "/home/biogeek/code/programname/env/lib/python3.6/site-packages/setuptools/_distutils/dist.py", line 967, in run_commands
self.run_command(cmd)
File "/home/biogeek/code/programname/env/lib/python3.6/site-packages/setuptools/_distutils/dist.py", line 984, in run_command
cmd_obj = self.get_command_obj(command)
File "/home/biogeek/code/programname/env/lib/python3.6/site-packages/setuptools/_distutils/dist.py", line 859, in get_command_obj
cmd_obj = self.command_obj[command] = klass(self)
File "/usr/lib/python3.6/distutils/cmd.py", line 57, in __init__
raise TypeError("dist must be a Distribution instance")
TypeError: dist must be a Distribution instance
编辑 2
我终于安装成功了。我尝试了一些东西,所以不完全确定最终是什么解决了这个问题,但是我:
- 已将
setuptools
从50.0.0
降级为41.0.0
- 将
setuptools
作为我的需求文件的第一行(参见 here) - 添加了一个粗糙的、hacky 的一次性函数,以指向具有名称 @url 语法的 zip 存档。
def _format_requirement(req):
if str(req.requirement) == 'git://github.com/BioGeek/tta_wrapper.git@master#egg=tta_wrapper':
return 'tta_wrapper @ https://github.com/BioGeek/tta_wrapper/archive/v0.0.1.zip'
return str(req.requirement)
您只能使用PEP 508 - Dependency specification for Python Software Packages个要求。根据该标准,git://github.com/BioGeek/tta_wrapper.git@master#egg=tta_wrapper
不是有效语法。
setuptools
接受 name@ url
direct reference syntax:
tta_wrapper @ git://github.com/BioGeek/tta_wrapper.git
你不能把它放在 requirements.txt 文件中,但是 和 不能使用 -e
开关。后者只能取VCSURL或本地文件路径,不是需求规范;见 Requirements File Format section.
所以你在这里进行了格式转换。我会检查 parse_requirements()
生成的 ParsedRequirement
对象上的 is_editable
标志,并相应地改变行为。您必须将要求字符串解析为 URL,取出 #egg=
片段并将其放在前面:
from urllib.parse import urlparse
def _format_requirement(req):
if req.is_editable:
# parse out egg=... fragment from VCS URL
parsed = urlparse(req.requirement)
egg_name = parsed.fragment.partition("egg=")[-1]
without_fragment = parsed._replace(fragment="").geturl()
return f"{egg_name} @ {without_fragment}"
return req.requirement
def load_requirements(fname):
"""Turn requirements.txt into a list"""
reqs = parse_requirements(fname, session="test")
return [_format_requirement(ir) for ir in reqs]
上面然后把-e git:...#egg=tta_wrapper
变成tta_wrapper @ git:...
:
>>> load_requirements('./requirements/dev.txt')
['tta_wrapper @ git://github.com/BioGeek/tta_wrapper.git@master', 'black==20.08b1']
在我的情况下,我的要求中没有任何 github link,但是行
-r common.txt
在 ./requirements/prod.txt
中导致了同样的错误。
我添加了愚蠢的条件,现在对我有用了:
def load_requirements(filename) -> list:
requirements = []
try:
with open(filename) as req:
requirements = [line for line in req.readlines() if line.strip() != "-r common.txt"]
except Exception as e:
print(e)
return requirements