如何import PipSession和parse_requirements


# 如何import PipSession和parse_requirements

在我们写setup.py中,我们希望setup.py能和 requirement.txt共用一份依赖配置,那么我们的思路自然是将requirement.txt的内容解析出来,加入到setup.py中的install_requires中。

对于requirements.txt的解析,pip中提供了parse_requirements方法。

parse_requirements的函数原型:

parse_requirements(filename: str, session: pip._internal.network.session.PipSession, finder: Optional[ForwardRef('PackageFinder')] = None, options: Optional[optparse.Values] = None, constraint: bool = False) -> Iterator[pip._internal.req.req_file.ParsedRequirement]
1

也就是它至少需要传入requirement.txt文件路径和PipSession两个参数。

不过比较坑的是,不同版本的pipimportparse_requirementsPipSession的路径不一样。

目前可以这样做最大兼容:

try:
    # pip >=20
    from pip._internal.network.session import PipSession
    from pip._internal.req import parse_requirements
except ImportError:
    try:
        # 10.0.0 <= pip <= 19.3.1
        from pip._internal.download import PipSession
        from pip._internal.req import parse_requirements
    except ImportError:
        # pip <= 9.0.3
        from pip.download import PipSession
        from pip.req import parse_requirements
1
2
3
4
5
6
7
8
9
10
11
12
13

requirements.txt文件的解析方法也需要做一定的兼容:

here = os.path.dirname(__file__)
# parse_requirements() returns generator of pip.req.InstallRequirement objects
if os.path.exists(os.path.join(here, "requirements.txt")):
    install_reqs = parse_requirements(os.path.join(here, "requirements.txt"), session=PipSession())
else:
    install_reqs = []
requirements = list() 
try:
    requirements = [str(ir.req) for ir in install_reqs]
except:
    requirements = [str(ir.requirement) for ir in install_reqs]
1
2
3
4
5
6
7
8
9
10
11