Auto Update Your Pypi Package
Post

Auto Update Your Pypi Package

Sometimes we mgiht want to make our package update to latest version, let me show you how do I accomplish this.

Determine Versions

We have to determine current installed package version.

1
2
3
4
5
6
7
8
def get_pkg_version(name):
    """Get current version of a installed pip package."""
    import pkg_resources

    try:
        return pkg_resources.require(name)[0].version
    except pkg_resources.DistributionNotFound:
        return None

Then detemine latest published version, if this is an internal package, you have to implement a custom method like bellow.

1
2
3
4
5
6
7
8
9
10
def get_latest_version(name, server='https://pypi.org'):
    import re
    import urllib.request, urllib.error

    try:
        content = str(urllib.request.urlopen('{}/simple/{}/'.format(server, name)).read())
        versions = re.findall('([^-<>]+).tar.gz', content)
        return versions[-1]
    except urllib.error.HTTPError:
        return None

Update Methods

We will use pip to update the package, here is the implementation.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import os
import sys

def get_python_cmd():
    """Get current running python executable"""
    return sys.executable


def update_pkg(name, *args):
    """Update a pypi package with pip."""

    arguments = [get_python_cmd(), '-m pip install -U', name]
    arguments.extend(args)
    cmd = ' '.join(arguments)

    print('Update {}: \n{}\n'.format(name, cmd))
    os.system(cmd)

The update method leaves *args is for internal package, you might want to parse in --extra-index-url and --trust-host.

Combine Together

Finally, we implement the auto update method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# auto_update.py
import os

from utility import get_pkg_version, get_latest_version, update_pkg

NAME = 'your_pkg_name'

def check_update(install=True):
    """Check update for the package."""
    latest_version = get_latest_version(NAME)
    installed_version = get_pkg_version(NAME)
    
    if latest_version is None or install_version is None:
        return

    if latest_version != installed_version:

        if install:
            update_pkg(NAME)
        else:
            print('New version of {} is available, {}=>{}.'.
                  format(NAME, installed_version, latest_version))

Then, we place it in __init__.py in root of package, every time the package be imported, it will run the auto checker.

1
2
3
4
# your_pkg/__init__.py
from auto_update import check_update

check_update()

OK, we have done the auto update.

Can Be Improved

In above example, we did not reload the module if there is an update, that depends on you.

Another thing can be improved is, we might not want to update the pacakge when there is an update, we just want to update it if there is a major / breaking update, the updator should be smarter.

将xmind文件转成可编程数据类型

用 Python 实现简单的 switch/case 语句