msizの日記

ソフトウェア関係の覚え書きが中心になる予定

Packaging Python Projectsの日本語仮訳

少し調べてたんで、はてな記法の練習も兼ねてPackaging Python Projects — Python Packaging User Guideの日本語版の仮訳を投稿。

原文のライセンスはCreative Commons Attribution-ShareAlikeというものですので、必要に応じて参照ください。

当然、日本語の誤記などは私の責任なので、そのあたりは原文の作者へは問合せしないようにしてください。



Pythonプロジェクトのパッケージ化 (Packaging Python Projects)

このチュートリアルは、シンプルな Python プロジェクトをどのようにパッケージするかひと通り試します。必要なファイルを追加してパッケージを作成するための構造にするにはどうするか、どのようにパッケージを作成し、どのように Python Package Index へアップロードするかを示します。

シンプルなプロジェクト (A simple project)

このチュートリアルでは example_pkg というシンプルなプロジェクトを利用します。 Python のモジュールや import packages (注: __init__.py のあるパッケージのことと考えれば大体合ってるはず)に慣れていない場合は、少し時間をとって Python documentation for packages and modules に目をとおすとよいでしょう。パッケージ化したいプロジェクトが既にあるとしても、このパッケージ例にはそのまま従ってチュートリアルを進め、それから自分のパッケージを試すことを推奨します。

手元(ローカル)でこのプロジェクトを作成するために、以下に示す構造でファイルを作成します:

/packaging_tutorial
  /example_pkg
    __init__.py

この構造で作成したら、このチュートリアルで示す全てのコマンドは一番上のフォルダで実行します - ですので cd packaging_tutorial を実行しておいてください。

さらに example_pkg/__init__.py を編集し、以下のコードを書いておきます。

name = "example_pkg"

これは、適切にインストールされたことをこのチュートリアルの後の方で確かめたり、 PyPI で使われていないことを確かめたりできるようにするためです。

パッケージファイルの作成 (Creating the package files)

これから、このプロジェクトをパッケージ化して配付の準備をするために、いくつかファイルを作成します。以下にリストされている新規ファイルを作成します - それらの内容は、これから示すステップに従って加えていきます。

/packaging_tutorial
  /example_pkg
    __init__.py
  setup.py
  LICENSE
  README.md

setup.py作成 (Creating setup.py)

setup.pysetuptools のビルド・スクリプトです。それはあなたのパッケージに関すること(例えば名前やバージョン)を、どのコードを含めるべきかということと同様に、 setuptools へ教えます。

setup.py を開き、以下の内容を入力してください。このチュートリアルをフォローする他の人達がアップロードしたパッケージと衝突しない固有のパッケージ名に確実になるように、パッケージ名をあなたの名前を含める(例えば、 example-pkg-theacodes )ように更新してください。

import setuptools

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

setuptools.setup(
    name="example-pkg-your-username",
    version="0.0.1",
    author="Example Author",
    author_email="author@example.com",
    description="A small example package",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/pypa/sampleproject",
    packages=setuptools.find_packages(),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires='>=3.6',
)

setup() はいくつかの引数をとります。このパッケージの例で使用しているのは、比較的最小のセットです:

  • name はパッケージの配付名です。これは「文字、数字、_、-」(letters, numbers, _, -)だけを含んでいさえすれば、どんな名前でも構いません。さらに、 pypi.org にはないものにする必要があります。あなたがアップロードする時点で既に登録されている名前と同じパッケージ名でアップロードしようとしないように、これを自分の名前で更新することを忘れないでください
  • version は、パッケージのバージョンです。詳細は PEP 440 を参照してください。
  • authorauthor_email は、このページの作者を特定するために使用します。
  • description は、短い一文のパッケージの要約です。
  • long_description は、パッケージの詳細な説明です。これはPython Package Index の package detail を示します。この例の場合、 long description は README.md から読み込まれます。
  • url は、プロジェクトのホームページのURLです。多くのプロジェクトで、これは単に GitHub, GitLab, Bitbucket または同様のホスティングサービスへのリンクです。
  • packages は、 distribution package に含まれる Pythonimport packages を全てリストします。手作業で各パッケージをリストする代わりに、 find_packages() を使うと、自動的に全てのパッケージとサブパッケージを見つけることができます。
  • classifiers は、 indexと pip にパッケージについてのいくつかの追加メタデータを与えます。この例の場合、パッケージは Python 3とだけ互換性があり、ライセンスは MIT ライセンスであり、 OS には非依存です。最低限でも、パッケージはどのバージョンの Python で動作し、どのライセンス下で使用可能であり、どのオペレーティングシステムで動作するかを含めるべきです。 classifiers の完全なリストは、 https://pypi.org/classifiers/ を参照してください。

さらに、ここでは紹介していないものもたくさんあります。詳細は Packaging and distributing projects を参照ください。

README.mdの作成 (Creating README.md)

README.md を開き、以下の内容を記入します。好きなようにカスタマイズしても構いません。

# Example Package

This is a simple example package. You can use
[Github-flavored Markdown](https://guides.github.com/features/mastering-markdown/)
to write your content.

LICENSE(ファイル)の作成 (Creating a LICENSE)

Python Package Index にアップロードされる全てのパッケージにとってラインセンスを含めることは重要です。これはパッケージをインストールするユーザにに、どの規約の下でパッケージを使用可能かを伝えます。ライセンスを選ぶには、 https://choosealicense.com/ を参照してください。一度ライセンスを選んだら、 LICENSE を開き、ライセンスの文章を記入します。例えば、 MIT ライセンスを選択した場合:

Copyright (c) 2018 The Python Packaging Authority

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

配付アーカイブの作成 (Generating distribution archives)

次のステップはパッケージの distribution packages の作成です。これは Python Index にアップロードされ、pip でインストールできるようになるアーカイブです。

最新バージョンの setuptoolswheel がインストールされていることを確認してください。

python3 -m pip install --user --upgrade setuptools wheel

(もしここで問題があれば、 Installing Packages を参照してください)

確認できたら setup.py があるディレクトリでこのコマンドを実行します。

python3 setup.py sdist bdist_wheel

このコマンドはたくさんのテキストを出力し、完了したら dist ディレクトリにファイルを2つ作成するはずです:

dist/
  example_pkg_your_username-0.0.1-py3-none-any.whl
  example_pkg_your_username-0.0.1.tar.gz

(もしここで問題が起きたら、出力内容をコピーして、 packaging problems に issue を登録するようお願いします。できる限りの手助けをします。 )

この tar.gz ファイルは source archive.whl ファイルは built distribution です。新しいバージョンの pip ではなるべく built distribution をインストールしようとし、必要な場合には source archive にフォールバックします。 source archive は常にアップロードし、プロジェクトが対応しているプラットフォームへは built archive を提供するべきです。この例の場合、パッケージはどのプラットフォームへも互換性があるので、必要な built distribution は1つだけです。

配付アーカイブのアップロード (Uploading the distribution archives)

ついに、パッケージを Python Package Index にアップロードするときです!

最初に必要なことは Test PyPI にアカウントを登録することです。 Test PyPY は、テストおよび実験のため別に用意された package index です。このチュートリアルのように本当の index へアップロードをしたくはない場合には素晴しいものです。アカウントを登録するためには、 https://test.pypi.org/account/register/ へ行きそのページ上のステップを完了します。そのとき、パッケージをアップロードできるようになる前に、 email アドレスの確認が必要になります。 Test PyPI についてのさらなる詳細は、 Using TestPyPI を参照してください。

登録ができたら、配付パッケージをアップロードするために twine を使うことができます。

python3 -m pip install --user --upgrade twine

一度インストールできたら、 dist の下にある全てのアーカイブをアップロードするために Twine を実行します。

python3 -m twine upload --repository-url https://test.pypi.org/legacy/ dist/*

Test PyPI に登録したユーザ名とパスワードを尋ねられるでしょう。コマンドが完了したら、以下のような出力が見られるはずです:

Uploading distributions to https://test.pypi.org/legacy/
Enter your username: [your username]
Enter your password:
Uploading example_pkg_your_username-0.0.1-py3-none-any.whl
100%|█████████████████████| 4.65k/4.65k [00:01<00:00, 2.88kB/s]
Uploading example_pkg_your_username-0.0.1.tar.gz
100%|█████████████████████| 4.25k/4.25k [00:01<00:00, 3.05kB/s]

一度パッケージをパッケージをアップロードしたら TestPyPI で、例えば https://test.pypi.org/project/example-pkg-your-username で見れるはずです。

新しくアップロードしたパッケージのインストール (Installing your newly uploaded package)

アップロードしたパッケージをインストールし動作するか確かめるには pip を使用できます。新しく virtualenv を作成して(やり方は https://packaging.python.org/tutorials/installing-packages/:Installing Packages を参照してください)、 TestPyPI からパッケージをインストールします。

python3 -m pip install --index-url https://test.pypi.org/simple/ --no-deps example-pkg-your-username

パッケージ名の中で自分のユーザ名を指定するのを忘れないでください。

pip は Test PyPI からパッケージをインストールし、以下のような出力をするはずです:

Collecting example-pkg-your-username
  Downloading https://test-files.pythonhosted.org/packages/.../example-pkg-your-username-0.0.1-py3-none-any.whl
Installing collected packages: example-pkg-your-username
Successfully installed example-pkg-your-username-0.0.1

(この例では --index-url フラグを使用して実際の PyPI の代わりに TestPyPI を指定しています。さらに、 --no-deps を指定しています。実際の PyPIと同じパッケージが TestPyPI にあるわけではないので、依存するものをインストールしようと試みたときに失敗したり予想と違うものをインストールしたりする可能性があります。この例のパッケージでは依存するものはないですが、 TestPyPI を使うときは依存するもののインストールを避けるのがノウハウです。)

適切にインストールされたかどうかは、モジュールを import し __init__.py で設定した name プロパティを参照することでテストできます。

Python インタプリタを実行します(まだ virtualenv 内であることを確認してください):

python

そしてモジュールを import し name プロパティを表示します。 setup.py の中で distribution package に自分の名前を含めていても(この例では、 example-pkg-your-username)、 import packageexample_pkg であるため、ここでの表示内容は以下のものと同じはずです。

>>> import example_pkg
>>> example_pkg.name
'example_pkg'

次のステップ (Next steps)

おめでとうございます、あなたは Python プロジェクトをパッケージ化し配付しました✨ 🍰 ✨

このチュートリアルは Test PyPI へパッケージをどうやってアップロードするかを示すもので、 Test PyPI はずっと保管をするわけではないことを覚えておいてください。そのテスト用システムはおりに触れて、パッケージとアカウントを消去することがあります。 Test PyPIは、このチュートリアルのようにテストや実験に使用するのが最適です。

本当のパッケージを Python Package Index へアップロードする準備ができたら、このチュートリアルと殆ど同じやり方でできますが、以下のような重要な違いもあります:

  • 覚え易くて他と重複しない名前をパッケージにつけてください。このチュートリアルのように、自分の名前をパッケージ名に含める必要はありません。
  • アカウントを https://pypi.org に登録してください - それは個別のサーバであり、 test サーバでのログイン詳細は main サーバとは共有されません。
  • パッケージのアップロードには twine upload dist/* を使用し、本当の PyPI で登録したログイン情報を入力してください。
  • 本当の PyPI からパッケージをインストールするときは pip install [your-package] を使用してください。

この時点で Python ライブラリのパッケージ化についてさらに読み進めたい場合は、以下のように進められます:


以上。

修正など、そのうち更新するかもしれません。