この記事では、Pythonのパッケージの作り方・PyPIで公開する方法を説明します。
もちろん、すでに同様の記事はあるのですが、情報が古かったり(後述)、一部のツール(TwineやPipenv)が紹介されていない記事が多いようなので、「2019年版」として最新と思われる方法を説明します。
使用するツール
以下のツールを使います。なお、この記事では、シンプルな(説明が楽な)ケースのみ説明しているので、詳細な使い方は各ツールのドキュメントを参照してください。
Setuptools
パッケージの内容を定義するための標準ライブラリ。setup.py
やsetup.cfg
などの設定ファイルはsetuptoolsが使う
Pipenv
開発中に、仮想環境を作ったり、依存パッケージを管理したり、Pythonのバージョンを切り替えるためのツール。サードパーティだがデファクトスタンダード。
pytest
サードパーティのテストライブラリ&テストランナー。
Twine
PyPIにパッケージをアップロードするためのサードパーティのツール。Setuptools自体にもアップロード機能があるが、Twineの方が使いやすいし、推奨されている。
事前準備
pipenv のインストール(pyenvを使っていない場合)
pipenv をインストールします。OSのPythonをそのまま開発に使う場合は、そのPythonにインストールすればOKです。
$ /usr/local/bin/pip3 install pipenv # システムのPythonにpipenvをインストール
pipenv のインストール(pyenvを使っている場合)
pyenv を使っていてPC内に複数のPythonインタープリタがある場合も、大抵の場合は pipenv はシステムのPythonにインストールすれば良い でしょう。
pipenv自体は、単にライブラリをDLしたり環境変数をセットしたりツールなので、使用するPythonとは独立して動作するからです(python 3.6にインストールした pipenv から python 3.7を実行したりできる)。
バージョンがすごく古いなどシステムのPythonを使えない場合は、 pyenv で最新のPythonをビルドして pipenv をインストールしてください。
ここで、インストールする際は --user
を付け、~/.local
にインストールするようにしてください。普通にインストールすると pyenv の管理対象になる(CLIでpipenvを実行するとき~/.pyenv/shims/pipenv
が参照される)ので、pyenv local
などでPythonを切り替えるとpipenvを使えなってしまいます。
$ .pyenv/versions/3.7.1/bin/pip install --user pipenv
$ export PATH=$PATH:~/.local/
$ pipenv # ~/.local/bin/pipenv を使用する
ソースコード・設定ファイルの作成
シンプルなパッケージなら、以下のようなファイル構成になります。
.
├── LICENSE # ライセンス
├── Pipfile # pipenvのパッケージ管理ファイル(開発用)
├── Pipfile.lock # pipenvのパッケージ管理ファイル(開発用)その2
├── README.md # README
├── setup.cfg # パッケージ名・バージョン情報などの設定ファイル
├── setup.py # お決まりのファイル
├── src
│ └── foo # Pythonのソースコード
│ ├── __init__.py
│ └── hoge.py
└── test # テスト
└── hoge_test.py
src/
(Pythonのソースコード)
何はともあれPythonのコードを書いてください。
# src/foo/hoge.py
def greet():
return 'hello'
# src/foo/__init__.py
# __init__.py は空でよい
なお、ルート直下にfoo/
を置いてもよい(そうしているプロジェクトも多い)のですが、src/foo/
とすることをお勧めします。直下に foo/
を置くと pipenvでインストール(後述)しなくても import できてしまい、混乱が起きるケースがあるためです。
README.md, LICENSE
書いてください。この段階では空でも問題ありません(リリース時までに書けばよい)。
setup.py
setup.py
は以下の内容にします。
from setuptools import setup
setup()
昔はパッケージ名やバージョンなどは setup.py
に書いていましたが、現在では setup.cfg
に書くのをお勧めします。特殊な処理をしない限り setup.py
に手を入れる必要はありません。
setup.cfg
setup.cfg
に、パッケージ名、バージョン番号、依存ライブラリなどを書きます。
[metadata]
name = foo
version = 0.0.1
description = Packaging sample project
long_description = file: README.md
long_description_content_type = text/markdown
license = BSD 3-Clause License # ライセンス名(省略可)
license_file = LICENSE
url = https://url/to/project/
[options]
package_dir=
=src
packages=find:
install_requires= # パッケージ自身の依存ライブラリ
psycopg2~=2.7.6
cx_Oracle==5.3
sqlalchemy~=1.2.0
[options.packages.find]
where=src
なお、「依存ライブラリ」には、実行時に必要なものと、開発時にのみ必要なものの2種類ありますが、
- パッケージの機能として必要なライブラリ →
setup.cfg
- 開発やテスト時のみ必要なライブラリ →
Pipfile
(後述)
と考えればOKです。
Pipfile
と Pipfile.lock
: pipenv のパッケージ管理ファイル(開発用)
以下のコマンドを実行すると、Pipfile
, Pipfile.lock
が作成された上で、開発用の仮想環境が作られます。
$ pipenv --python=3.7.1 install --dev -e .
開発用のライブラリを追加したい時は以下のコマンドを実行します。
$ pipenv install --dev pytest
テストの実行
test/
にテストコードを書きます。
import foo.hoge
def test_bar():
assert foo.hoge.greet() == 'hello'
Pythonのテストツールは複数ありますが pytest がメジャーなようです。pytest を実行すると、test/
中の、名前にtest
が付くファイルの、test
で始まる関数を実行してくれます。
$ pipenv install --dev pytest
$ pipenv run pytest
============================================================ test session starts ============================================================
platform darwin -- Python 3.7.1, pytest-4.4.0, py-1.8.0, pluggy-0.9.0
rootdir: /Users/k-omoto/Documents/foo
collected 1 item
test/hoge_test.py . [100%]
========================================================= 1 passed in 0.05 seconds ==========================================================
Twine: PyPI へのアップロード
さて、コードを全て書き、テストも完了したとしましょう。いよいよPyPIへのアップロードです(PyPI以外にアップロードする方法は後述)。
まず、PyPIにアカウントを持っていない場合は、アカウントを作成します。
twine をインストールします。
$ pipenv install --dev twine
PyPIにアップロードするアーカイブファイルを生成します。プレーンなPythonパッケージなら python setup.py sdist
で良いでしょう。
$ python setup.py sdist --formats=zip
$ ls dist/
foo-0.0.1.zip
生成したアーカイブファイルをtwine upload
に指定して実行するとPyPIにアップロードできます。必要に応じてユーザー名やパスワードを入力してください。
$ twine upload dist/foo-0.0.1.zip
PyPI以外へのアップロード
社内用のライブラリなど、PyPIではなく別のサーバーに公開したい場合は、環境変数 TWINE_REPOSITORY を追加してください。
$ export TWINE_REPOSITORY=社内レポジトリのURL
$ twine upload dist/foo-0.0.1.zip
補足: setup.cfg の entry_points
[entry_points]
を書くと、パッケージのインストール時にコマンドを自動生成できます。これを使えば、ライブラリだけでなくCLIツールもPyPI経由で公開できます。
以下のように書くと、foo.cli.main()
という関数を実行する、foo
という実行可能なファイル(スクリプト)が生成されます。
[entry_points]
console_scripts =
foo = foo.cli:main
補足: 古いツール
ググると以下のような、ツール・コマンドがヒットします。これらは古い方法なので、新しいプロジェクトでは使わないようにしましょう1。
- setup.py にパッケージ名やバージョン番号が書かれている
- → setup.cfg に書きましょう
- distutils
- パッケージング用の標準ライブラリ
- setuptoolsに取って代わられました
-
python setup.py register
python setup.py upload
- setuptools組み込みのアップロード機能です
- パスワードをHTTPで送っている問題がありました。Twineを使いましょう
- nose
- テストライブラリ・ツールです
- pytestの方が人気があるようです。
- requirements.txt
- 依存ライブラリを pip で管理するためのファイルです
- pipenv と
Pipfile
/Pipfile.lock
に取って代わられました
補足: なぜ Pipenvか?
Pipenvに疑問がある人も世の中にはいるようですが、今の所 Pipenv の方がメジャーそうだし、Pipenv を使って大いに困るということはなさそうなので、この記事では Pipenvを使っています。
また、Pipenv周りで混乱することがあったら、以下の記事が役立つかもしれません。
書かなかったこと(あとで追記するかも?)
- Cython:拡張ライブラリを実装する
- Sphinx:APIドキュメントを生成する
-
なお、これらの古い方法は今でも使うことはでき、パスワードをHTTPで送っている問題などを除けば、焦って書き換える必要はありません。 ↩