【问题标题】:PyPI API - How to get stable package versionPyPI API - 如何获得稳定的包版本
【发布时间】:2015-04-30 17:49:13
【问题描述】:

pip 如何确定哪个版本是软件包的稳定版本?例如,当前 Django 的稳定版本是1.7.5(截至 2015 年 2 月 27 日),也就是通过命令pip install django 安装的版本。

但是当我转到 PyPI JSON API for Django (https://pypi.python.org/pypi/Django/json) 时,它解析为最新版本(包括开发版本):

"version": "1.8b1",

在 JSON 响应中有一个看起来表明稳定的键:

"stable_version": null,

但是我在 API 中尝试的所有包的值都是null。 JSON 响应中有这一行:

"classifiers": [
    "Development Status :: 4 - Beta", 

但这是一个复杂的解析行。如果有像"stable_version": truefalse 这样的行就好了。如何使用 PyPI JSON API 确定默认 pip 安装版本?

【问题讨论】:

    标签: python pip pypi


    【解决方案1】:

    PEP-440 中定义的版本方案。有一个模块packaging,可以处理版本解析和比较。

    我想出了这个函数来获取一个包的最新稳定版本:

    import requests
    import json
    try:
        from packaging.version import parse
    except ImportError:
        from pip._vendor.packaging.version import parse
    
    
    URL_PATTERN = 'https://pypi.python.org/pypi/{package}/json'
    
    
    def get_version(package, url_pattern=URL_PATTERN):
        """Return version of package on pypi.python.org using json."""
        req = requests.get(url_pattern.format(package=package))
        version = parse('0')
        if req.status_code == requests.codes.ok:
            j = json.loads(req.text.encode(req.encoding))
            releases = j.get('releases', [])
            for release in releases:
                ver = parse(release)
                if not ver.is_prerelease:
                    version = max(version, ver)
        return version
    
    
    if __name__ == '__main__':
        print("Django==%s" % get_version('Django'))
    

    执行时,会产生以下结果:

    $ python v.py
    Django==2.0
    

    【讨论】:

    • 我通过如下修改这一行得到了这个工作j = json.loads(req.text.encode(req.encoding or "utf-8")) 因为 req.encoding 有时可能是空的。
    【解决方案2】:

    只是一个简短的说明(因为我还不能添加对先前答案的回复) sashk 的答案可能会返回不正确的答案,因为 max() 并不真正理解版本控制,f.e.截至目前,在 SQLAlchemy 上,它认为 1.1.9 高于 1.1.14(这实际上是最新的稳定版本)。

    快速解决方案:

    import urllib.request
    import packaging.version
    import distutils.version
    data = json.loads(urllib.request.urlopen('https://pypi.python.org/pypi/SQLAlchemy/json').readall().decode('utf-8'))
    max([distutils.version.LooseVersion(release) for release in data['releases'] if not packaging.version.parse(release).is_prerelease])
    

    正确返回

    LooseVersion ('1.1.14')
    

    【讨论】:

    • 我建议您提高第一段的清晰度。
    • ``` >>> from packaging.version 导入解析; a=parse('1.1.14'); b=解析('1.1.9'); max(a, b) ``` 按预期工作。也许,他们没有使用 PEP-440 格式的版本。
    猜你喜欢
    • 2015-01-17
    • 2013-11-19
    • 1970-01-01
    • 2018-08-03
    • 2023-03-20
    • 2020-07-16
    • 1970-01-01
    • 2017-02-13
    • 1970-01-01
    相关资源
    最近更新 更多