PyPIにパッケージ上げた

python


Slack の Slash Commands をササっとできるやつをパッケージにして配布しました。 なんだかんだPyPIにばらまくのは初めでして、 いろいろ古い方法も出回っていていい感じのやり方に到達するのに手を焼いたので、 これを機にパッケージ配布に必要なものをメモしておきます。

出てくる人たち

setup.py

Pythonのサードパーティーパッケージのインストールを行うための標準モジュールが、 setuptoolsと言う形で提供されています。 これでインストールしたパッケージはPythonのランタイムに配置され、 どこからでもimportできるようになります。 setuptoolsを利用し、独自パッケージをインストールするためのスクリプトは setup.py というファイル名を推奨されており、一般にも setup.py と呼ばれます。

まず、独自パッケージは大体以下のような形になっていると思います。

.
|__ your_package/
|   |__ __init__.py
|   |__ foo.py
|
|__ tests/
|   |__ __init__.py
|   |__ test_foo.py
|
|__ LICENSE
|__ README.md
|__ requirements.txt
|__ .travis.yml

これにsetuptoolsのためのファイルなどを追加していきます。

MANIFEST.in

配布パッケージには、以下のような要素があります。

  1. パッケージ情報を含んだメタ情報ファイル
  2. パッケージモジュール本体
  3. ドライバやバイナリなど、追加ファイル

このうち、2と3については後述するsetup.pyで指定することになりますが、 1についてはMANIFEST.inに指定します。 上に書いたファイル構造だと、MANIFEST.inの内容は以下のようになると思います。

include README.md LICENSE requirements.txt

MANIFEST.inに記述しなくても README, README.txt などは 自動的にパッケージに含まれますが、 基本的にパッケージに含まれるメタ情報ファイルは明示しておくことを推奨します。

setup.py

パッケージをインストールするため、また配布するために用意するファイルが setup.pyです。 このスクリプト内ではsetuptoolsというモジュールの機能を使い、 パッケージの情報を与えてセットアップを実行します。

setup.pyの基本的な形は以下のようになります。

from setuptools import setup, find_packages


setup(
    name='your_package',
    version='0.1',
    description='Your awesome package.',
    url='https://github.com/you/your_package',
    license='MIT',

    author='your name',
    author_email='your.name@example.com',

    # include all packages
    packages=find_packages(exclude=['tests', '.travis.yml']),

    install_requires=[
        'Flask==0.11.1',
    ],
    classifiers=[
        'Development Status :: 2 - Pre-Alpha',
        'Intended Audience :: Developers',
        'Environment :: Web Environment',
        'License :: OSI Approved :: MIT License',
        'Operating System :: POSIX :: Linux',
        'Programming Language :: Python :: 3.6',
        'Topic :: Internet :: WWW/HTTP'
    ],
)

注意する情報としては、

argument value
name パッケージの名前になります
version ビルドの際必要になります
packages パッケージに含まれるファイルの一覧です
install_requires 依存サードパーティーパッケージです

packagesが指定されなかった場合、distutilの仕様 に従って、PythonスクリプトやCライブラリなどが自動的に含まれます。 ただ、明示することを推奨します。 また、setuptools.find_packagesのような便利なモジュールも提供されています。

setuptoolsのTipsについては、setuptoolsのドキュメンテーションが豊富です。

Building and Distributing Packages with Setuptools

Classifiers

そのパッケージがどんなものなのか、 どんな人に向けたものなのかを教えるための標準的な仕様として、 classifiersが提供されています。 classifiersの一覧は以下にあります。

List trove classifiers - PyPI - Python

メタ情報について

パッケージのバージョンなどは、 モジュールが持つ値としてPythonスクリプト内で参照 できることを望まれる場合があります。 そのため、慣習的にパッケージのメタ情報をモジュール内に埋め込む文化があります。 これは使っているVCSの理念などにもよるものと思いますので、好みの内容です。

具体的に説明します。 パッケージのメタ情報をyour_package.__meta__と言う形で取得したいので、 your_package/__init__.pyにその情報を書き込みます。

# your_package/__init__.py
__author__ = 'your name'
__version__ = '0.1'
__license__ = 'MIT'

こんな感じに情報を書き加えた上で、 setup.py

import your_package

setup(
    ...,
    author=your_package.__author__,
    version=your_package.__version__,
    license=your_package.__license__,
    ...
)

などとすると、バージョンを切るときに setup.py のリビジョンの変更ができなくて綺麗になると思います。

また、__init__.py にdocstringを記述した場合your_package.__doc__で参照できるため、 long_descriptionにdocstringを入れるといい感じになると思います。

配布手順

PyPI の登録

まずはpip installできるパッケージをホストするレジストリ、 PyPIを利用するためにPyPIにユーザー登録をします。

PyPI - the Python Package Index

Registerからユーザー名とパスワード、メールアドレスを設定して登録申請します。 すると設定したメールアドレス宛に確認メールがきますので、 そのURLを踏んで最終確認事項を読み、 了承して確定するとユーザー名とパスワードでログインできるようになります。 URL踏んだだけじゃ登録完了にならないよ!

これでPython開発者として登録されます。

.pypirc 設定

PyPIをはじめとするpipレジストリへアクセスするためにはユーザー情報が必要ですが、 これらの情報をまとめた ~/.pypirc を用意すると便利です。

.pypircでは、pipのレジストリ(正しくはdistutilsのですが)の一覧、 それらへアクセスするための情報を記述することができます。

setup.py は自動的にホームディレクトリに置かれた .pypirc を読み、 レジストリへ読み書きします。

[distutils]
index-servers=
    pypi
    testpypi

[testpypi]
repository = https://testpypi.python.org/pypi
username = your_username
password = your_password

[pypi]
repository = https://pypi.python.org/pypi
username = matsub
password = your_password

password項目は省略することができ、 省略した場合はsetuptoolsの実行時にパスワードを問われます。

testpypi

setuptoolsのテストを行うために、 同様の挙動を行ってくれるtestpypiというホスティングがあります。 こちらを利用したい場合は別にユーザー登録が必要となりますので、 PyPIと同様の手順でユーザー登録をしてください。

ビルド、アップロード

setup.py が用意できたら、以下の4つの行程を済ませれば配布完了です。 もう pip install できます。

  1. python setup.py sdist bdist_wheel
  2. twine register dist/project_name-x.y.z.tar.gz
  3. twine register dist/mypkg-0.1-py2.py3-none-any.whl
  4. twine upload dist/*

それぞれ説明していきます。

setuptools

まず最初のコマンドについて、setuptools関連です。 最初のコマンド python setup.py sdist bdist_wheel は配布するパッケージのディストリビューションをビルドするコマンドです。 パッケージ配布には2種類の要素があり、 それぞれ sdist(source distribution), bdist(binary distribution)です。 ソースコードの配布はシンプルになりますが、 バイナリの配布は環境依存が発生するので、統一されたフォーマットが必要になります。 そのフォーマットのひとつがwheelです。 昔はeggとかあったらしいけど今はwheelが推奨されています。

setuptools は setup.py で記述されたバージョンをラベルにビルドします。 新しいバージョンを作成した場合は新たにビルドする必要があります。

wheel形式のbdistをビルドするためには、パッケージ wheel が必要になります。

$ pip install wheel

twine

twineはPyPIへの一連のメタ情報をあらかじめ含んだ、PyPIへのインターフェースです。 現在、パッケージ配布にはこれが推奨されています。 以前は python setup.py register -r wtf などの一連のコマンドを打ち込み、

  1. PyPIへのパッケージ登録
  2. パッケージ情報設定
  3. 各パッケージアップロード

をそれぞれ行う必要がありましたが、 twineはその一連の作業を簡略化したものです。多分。 手順は、setuptoolsでビルドして、ソースを登録して、wheelオブジェクトを登録して、 アップロードするだけ。まあそらそうだって感じで覚えやすいですね。

なお、register は初回のみ必要で、 それ以降は upload ごとに最新版が書き込まれていきます。

twineを使用するためには、パッケージ twineが必要になります。

$ pip install twine

おまけ

今回作ったやつはこれです

自分で作ったやつがpipで落とせると興奮するね。