Help us understand the problem. What is going on with this article?

Python パッケージを作成&PyPIで公開する方法 - 2019年版

この記事では、Pythonのパッケージの作り方・PyPIで公開する方法を説明します。

もちろん、すでに同様の記事はあるのですが、情報が古かったり(後述)、一部のツール(TwineやPipenv)が紹介されていない記事が多いようなので、「2019年版」として最新と思われる方法を説明します。

使用するツール

以下のツールを使います。なお、この記事では、シンプルな(説明が楽な)ケースのみ説明しているので、詳細な使い方は各ツールのドキュメントを参照してください。

Setuptools
パッケージの内容を定義するための標準ライブラリ。setup.pysetup.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です。

PipfilePipfile.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周りで混乱することがあったら、以下の記事が役立つかもしれません。

Pythonのパッケージ周りのベストプラクティスを理解する

書かなかったこと(あとで追記するかも?)

  • Cython:拡張ライブラリを実装する
  • Sphinx:APIドキュメントを生成する

  1. なお、これらの古い方法は今でも使うことでき、パスワードをHTTPで送っている問題などを除けば、焦って書き換える必要はありません。 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away