10
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Python】PyPIに自作ライブラリを登録する

Last updated at Posted at 2020-05-05

はじめに

本記事は、パッケージの作成からPyPIに登録までの方法を記します。
どちらかというと、備忘録的な感じです。

自作パッケージ公開までの流れ

自作パッケージを公開するまでの流れは以下の通りです。
6ステップでPyPIに公開できます。
(この中で一番大変なのは、(1 )のパッケージ作成の部分です)

  1. パッケージ作成(Pythonでコーディング)
  2. pip でインストールできるように設定ファイルの追加
  3. 配布物の作成
  4. test-PyPIにテスト登録
  5. PyPIに登録
  6. deploy の自動化

1. ライブラリ作成

<package_name>にはライブラリの名前にしておくといいです。
numpypandasscikit-learnなどはこの形式です。
ただ、matplotlibは、srcになっているなど例外もあります。

├─ <package_name>/
|  └─ __init__.py
└─ README.md

そして、この<package_name>直下にある__init__.pyで宣言された関数や変数が、
import後利用できるようになります。pandasの例で言うと、以下の通りです。

import pandas as pd
pd.read_csv("...")

として、pd.read_csv()が利用できるのは、__init__.pyの中に関数が宣言されているためです。
(厳密には、__init__.pyの中ではread_csv()そのものは定義されていません)。

例として、Hogeクラスを定義しておきます。

__init__.py
class Hoge:
    def __init__(self):
        pass

このようにしておくと、以下のように利用できます。

main.py
import <package_name>

hoge = <package_name>.Hoge()

2. 設定ファイルの追加

適当なライブラリのクラスを定義・作成したら、次は公開の準備をすすめていいきましょう。
最低限必要なファイルはsetup.pyのみです。

setup.pyは、パッケージの情報を記載します。
詳しくは「PyPIパッケージ定義ファイル作成方法 - init.py setup.py MANIFEST.in の書き方」をご覧ください。

setup.py
import setuptools

with open("README.md", "r") as fh:
    long_description = fh.read()


setuptools.setup(
    name="<package name>",
    version="<version>",
    author="<your name>",
    author_email="<your email>",
    description="<short_description>",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/<your_github_name>/<repository_name>",
    packages=setuptools.find_packages(),
    install_requires=[
        "pandas>=1.0.0",
        "s3fs>=0.4.2"
    ],
    license="MIT",
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires='>=3.7',
)

また、必要に応じてMANIFEST.inを作成します。
これは、配布するパッケージに含める/除くファイルを決められます。

MANIFEST.in
include MANIFEST.in
include setup.py
include README.md

setup.pyMANIFEST.inを追加したあとのファイル構成は以下の通りです。

├─ <package_name>/
|  └─ __init__.py
├─ setup.py
├─ MANIFEST.in (必要に応じて)
└─ README.md

3. 配布物の作成

setup.pyを作成したら、いよいよPyPIに登録していきます。
配布用のパッケージ作成とPyPIにアップロードするように以下のパッケージを install します。

$ pip install twine wheel

次のコマンドを実行し、ソースコード配布物を作成し、ライブラリのパッケージを作成します。

$ python setup.py sdist bdist_wheel

すると、以下のようにフォルダ作成されます。

├─ <package_name>/
|  └─ __init__.py
├─ <package_name>.egg-info/
├─ dist/
├─ setup.py
├─ MANIFEST.in (必要に応じて)
└─ README.md

それぞれのファイルは、以下の通りです。

  • <パッケージ名>.egg-info ディレクトリ
    ソースコード配布物作成時の中間ファイルが書き出されるディレクトリです。
    MANIFEST.in から配布物に含めるファイルを削ったとき、それだけでは反映されず、同ディレクトリのファイルを一度削除してリセットする必要があります。
  • dist ディレクトリ
    パッケージファイルが書き出されるディレクトリです。
    パッケージファイルは、同ディレクトリに追加作成されます。
    PyPIに不要なファイルをアップロードしてしまわないよう、最初にファイル削除することをお勧めします。

また、パッケージをアップデートする際には以下のコマンドを打ち、
以前のバージョンの配布物が入ってる<package_name>.egg-infoと dist 以下の中身を消すようにしましょう。
これらのファイルは再生成できるため削除してしまって構わないです。

$ rm -f -r <package_name>.egg-info/* dist/*

4. test-PyPIに登録・アップロード

配布物の作成が終わったら、test-PyPIにテスト登録をしてみましょう。
test-PyPIでアカウントを作成し、以下のファイルをホームディレクトリに作成します。
(以下ファイルには本番PyPIの情報も記述してあります)

~/.pypirc
[distutils]
index-servers =
  pypi
  testpypi

[pypi]
repository: https://upload.pypi.org/legacy/
username: <本番用アカウント名>
password: <パスワード>

[testpypi]
repository: https://test.pypi.org/legacy/
username: <テスト用アカウント名>
password: <パスワード>

~/.pypircの作成が終わったら、次のコマンドを実行し、test-PyPIに登録します。

$ twine upload -r testpypi dist/*

test-PyPIに登録ができたら、pipでインストールできるか確認しましょう。

$ pip install -i https://test.pypi.org/simple/ <package_name>

また、poetryを利用している場合は以下のpyproject.tomlに以下を追加します。

pyproject.toml
+ [[tool.poetry.source]]
+ name = "testpypi"
+ url = "https://test.pypi.org/simple/"
+ secondary = true

[tool.poetry]
name = "python_env"
version = "0.1.0"
description = ""
authors = ["your_email"]

[tool.poetry.dependencies]
python = "^3.7"
pandas = "^1.0.3"

[tool.poetry.dev-dependencies]

[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

そうすると、通常のpoerty addコマンドでインストールできるようになります。

$ poerty add <package_name>

このtest-PyPIを利用して、pipでインストールできるか確認すると良いです。
ちなみに、test-PyPIに登録して実際にpipでインストールできるようになるまで最大で10分程度かかりました。

5. PyPIに登録

test-PyPIから正しくpip installができたら、https://pypi.python.org/に登録しましょう。
まずは、test-PyPIと同様にユーザーアカウントを作成し、~/.pypircにアカウント情報を追記します。

すでに、配布物は作成済みなので、以下のコマンドを実行するだけです。

$ twine upload -r pypi dist/*

実行後は、PyPIに登録されているか確認後、実際にpip installしてみましょう。
(poerty などで実行する場合は、追加した url を削除しておきましょう)

test-PyPIに登録が成功すれば、PyPIへの登録もすぐできます。

6. deployの自動化

毎回、同じコマンドを実行するのは大変なので
1つのコマンドで自動削除・配布分作成・PyPI登録してくれるようにMakefileを作成しましょう。

※この時、:の後に続くのはspaceですが、先頭から文字を入力する場合は、tabじゃないとMakefile:-: *** missing separator. Stop.というエラーが出ます。
(Qiita では表示の都合上 space になっているのでそのままコピーしてもエラーになります)

Makefile
.PHONY: deploy
deploy: build
	twine upload dist/*

.PHONY: test-deploy
test-deploy: build
	twine upload -r testpypi dist/*

.PHONY: build
build: clean
	python setup.py sdist bdist_wheel

.PHONY: clean
clean:
	rm -f -r azfs.egg-info/* dist/* -y

上記のようなMakefileを作成し、以下のコマンドを実行するとPyPIに登録してくれます。

# テストPyPIの場合
$ make test-deploy

# 本番PyPIの場合
$ make deploy

おわりに

一通り、パッケージ作成からPyPI登録までの流れを記事にしてみました。
これで皆さんもパッケージ配布できますね。

2020/05/09追記

poetryならもっと簡単にできました。

test-PyPIに登録

# test-pypiのurlを登録
$ poetry config repositories.testpypi https://test.pypi.org/legacy/
$ poetry config --list

> cache-dir = "/Users/<user_name>/Library/Caches/pypoetry"
> repositories.testpypi.url = "https://test.pypi.org/legacy/"
> virtualenvs.create = true
> virtualenvs.in-project = true
> virtualenvs.path = "{cache-dir}/virtualenvs"  # /Users/<user_name>/Library/Caches/pypoetry/virtualenvs

$ poetry build
$ poetry publish -r testpypi -u <user_name> -p <password>

PyPIに登録

$ poetry build
$ poetry publish -u <user_name> -p <password>

参考

10
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?