Skip to content

Latest commit

 

History

History
124 lines (92 loc) · 4.52 KB

Check-Python-site-packages-for-Updates.rst

File metadata and controls

124 lines (92 loc) · 4.52 KB

为Python site-packages检查更新

原文: Check Python site-packages for Updates

译者: youngsterxyf

刚才,我找到一个美妙的短小脚本 check_for_updates.py ,它使用PIP来为本地已安装的Python包检查更新。然而,在Python 3环境下无法工作,所以我就把它移植过来了:

"""
Use pip to get a list of local packages to check against one or more package
indexes for updated versions.

"""
try:
    from cStringIO import StringIO
    import xmlrpclib
except ImportError:
    from io import StringIO
    import xmlrpc.client as xmlrpclib

from distutils.version import StrictVersion, LooseVersion
import sys

import pip


def get_local_packages():
    """
    Call pip's freeze -l

    returns a list of package_name, version tuples

    """
    sys.stdout = mystdout = StringIO()
    pip.main(['freeze', '-l'])
    sys.stdout = sys.__stdout__

    pkgs = mystdout.getvalue().split('\n')
    return [p.split('==') for p in pkgs]


def find_current_version(package, index_urls=None):
    """
    Using the XMLRPC method available for PyPI, get the most recent version
    of <package> from each of the index_urls and figure out which one (if any)
    is higher

    Returns a tuple of the index with the higher version and the version it has

    """
    if index_urls is None:
        index_urls = ['http://pypi.python.org/pypi']
    cur_version = '0'
    cur_index = ''
    for index_url in index_urls:
        pypi = xmlrpclib.ServerProxy(index_url, xmlrpclib.Transport())
        pypi_hits = pypi.package_releases(package)
        if len(pypi_hits) > 0:
            if compare_versions(pypi_hits[0], cur_version):
                cur_version = pypi_hits[0]
                cur_index = index_url

    return cur_index, cur_version


def compare_versions(version1, version2):
    """
    Compare 2 versions, starting with StrictVersion, and falling back on
    LooseVersion. Returns ``True`` if *version1* is greater than *version2*.

    """
    try:
        return StrictVersion(version1) > StrictVersion(version2)
    # in case of abnormal version number, fall back to LooseVersion
    except ValueError:
        return LooseVersion(version1) > LooseVersion(version2)


def output_line(pkg_name, new_version, old_version, index_url):
    """Output the line showing the formatted information."""
    msg = '%(bd)s%(pkg_name)s%(nm)s (%(new)s) via %(index)s. Currently %(old)s.'
    params = {
        'bd': BOLD,
        'nm': NORMAL,
        'pkg_name': pkg_name,
        'new': new_version,
        'old': old_version,
        'index': index_url,
    }
    print(msg % params)


NEWER = lambda x, y: compare_versions(str(x), y) == 1


if __name__ == '__main__':
    import curses
    curses.setupterm()
    CLEAR_SCREEN = curses.tigetstr('clear').decode('utf-8')
    BOLD = curses.tigetstr('bold').decode('utf-8')
    NORMAL = curses.tigetstr('sgr0').decode('utf-8')

    if len(sys.argv) > 1:
        indexes = sys.argv[1:]
    else:
        indexes = ['http://pypi.python.org/pypi']
    print(CLEAR_SCREEN + BOLD + 'Packages with newer versions:' + NORMAL)
    print('')

    for pkg in get_local_packages():
        # pip outputs a single 0 at the end of the list. Ignore it.
        if len(pkg) < 2:
            continue

        index, current_version = find_current_version(pkg[0], index_urls=indexes)
        if current_version and NEWER(str(current_version), pkg[1]):
            output_line(pkg[0], current_version, pkg[1], index)

可以随便在哪使用某个Python解释器来执行这个脚本(例如,python3 check_for_updates.py或者在一个virtualenv环境中运行),如果你想为这个Python解释器检查其程序包的更新信息。然后,你就可以使用 pip install -U <packagename> (对于Python 3则是pip-3.2)来更新程序包。

更新yolk 程序包可以通过 yolk -U 来完成上述脚本同样的事情,只是它不支持Python 3。我就在想PIP什么时候能包含这个功能。