AttributeError: 'ParsedRequirement' object has no attribute 'req'

AttributeError: 'ParsedRequirement' object has no attribute 'req'

我有 docker 文件,其中一层为

RUN python setup.py develop

我正在使用具有三个阶段的多阶段构建,这是第一个阶段,所有阶段都具有相同的基本图像,尽管我认为这不是 dockerfile 的问题,但似乎成为 python 及其执行方式的问题 处理基本图像 python:3.7-slim 我正在 Travis CI 上构建这个 docker 文件,下面是这个 Travis 的版​​本信息:

docker version
Client:
 Version:      17.09.0-ce
 API version:  1.32
 Go version:   go1.8.3
 Git commit:   afdb6d4
 Built:        Tue Sep 26 22:42:38 2017
 OS/Arch:      linux/amd64
Server:
 Version:      17.09.0-ce
 API version:  1.32 (minimum version 1.12)
 Go version:   go1.8.3
 Git commit:   afdb6d4
 Built:        Tue Sep 26 22:41:20 2017
 OS/Arch:      linux/amd64
 Experimental: false

我得到以下错误,因为

AttributeError: 'ParsedRequirement' object has no attribute 'req'

令人惊讶的是,我能够在我的 mac machine 上使用 docker 版本 19.03.2 这是我的 setup.py 文件

import os
import shutil
import inspect
import platform
from setuptools import setup
import setuptools
try:
    from pip.req import parse_requirements
except ImportError:
    from pip._internal.req import parse_requirements

EMAIL_CONF = 'email.conf'
DL_CONF = 'dl.conf'
LINUX_CONFDIR = os.path.expanduser('~') + '/.config/bassa/'
WIN_CONFDIR = os.path.expanduser('~') + '/%app_data%/bassa/'
OSX_CONFDIR  = os.path.expanduser('~') + '/.config/bassa/'

# Utility function to read the README file.
def read(file_name):
    return open(os.path.join(os.path.dirname(__file__), file_name)).read()

base_dir = os.path.dirname(os.path.abspath(__file__))
requirements_path = os.path.join(base_dir, 'requirements.txt')

install_reqs = parse_requirements(requirements_path, session=False)

requirements = [str(ir.req) for ir in install_reqs]

### Set configs ###
if platform.system() == 'Linux':
    configdir = LINUX_CONFDIR
elif platform.system() == 'Windows':
    configdir = WIN_CONFDIR
elif platform.system() == 'Darwin':
    configdir = OSX_CONFDIR
if not os.path.exists(configdir):
    os.makedirs(configdir)

email_conf_location = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + "/" + EMAIL_CONF
dl_conf_location = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) + "/" + DL_CONF
shutil.copyfile(email_conf_location, configdir + EMAIL_CONF)
shutil.copyfile(dl_conf_location, configdir + DL_CONF)

###/ Set configs ###

setup(
   ...
)

请帮我解决这个问题。

更新:

* 请注意,我的情况不支持更新 pip 和 pip-tools。那么我的回答中的解决方法将会有所帮助。

* 如果支持将 pip 和 pip-tools 升级到兼容版本则参考 or

我终于搞定了\o/

install_reqs = parse_requirements(requirements_path, session=False)

起初,我通过简单地记录下来检查了 Travis 上的 install_reqs 是什么,发现它是一个 ParsedRequirement 对象的列表。我还发现这个class是在req_file.py中定义的。我去 GitHub 查看了 req_file.py here 的源代码。我发现没有名为 req 的属性,而是 requirement。所以有两个版本的 parse_requirements 函数,所以我使用 try 和 except 块来处理这个问题。

# Generator must be converted to list, or we will only have one chance to read each element, meaning that the first requirement will be skipped.
requirements = list(requirements) 
try:
    requirements = [str(ir.req) for ir in install_reqs]
except:
    requirements = [str(ir.requirement) for ir in install_reqs]

现在兼容两个版本\0/

我遇到了一个非常相似的问题和相同的错误消息。在使用 pip-tools / pip-compile / pip-sync 时发生。 该问题可能与 pip 和 pip-tools 的 non-compatible 版本有关,已通过更新 pip 和 pip-tools.

解决

解决这些问题可以消除 中解决方法的必要性。

我知道这与 Docker 中的错误没有直接关系,但我遇到了同样的错误并且在我用 Google 搜索时遇到了这个 post 并想加上我的两分钱 -

此错误肯定与pippip-toolspython版本不兼容有关。我查看了兼容版本 here 并将我的项目与它们匹配,错误已解决。

我会说,在你做任何其他事情之前先试试这个

我的解决方法:

try:
    # newest versions.
    # pip>=21.x.x
    from pip._internal.req.constructors import (
        install_req_from_parsed_requirement,
    )
except ImportError:
    # pip<=20.x.x
    def install_req_from_parsed_requirement(x):
        return x

# read your requirements.
install_reqs = parse_requirements(requirements_path, session=False)
# for pip==21.x.x convert ParsedRequirement into InstallRequirement.
install_reqs = [install_req_from_parsed_requirement(req) for req in install_reqs]

它提供了 pip 版本之间的透明兼容性。此外,如果您需要使用 InstallRequirement 方法和属性,例如 req、original_link 或 match_markers().

,它会非常有用