目次

はじめに
本書で解説することと、解説しないこと
サンプルコードについて
動作確認環境
免責事項
表記関係について
第1章 パッケージ作成の前提理解
1.1 PEPとは?PyPAとは?
1.2 モジュールとは?パッケージとは?
1.3 pipとは?wheelファイル形式とは?
1.4 仮想環境とは?(依存関係のローカルインストール方法)
1.5 パッケージ作成での推奨フォルダー構成
第2章 配布パッケージの作成手順
2.1 配布パッケージ作成ツールの種類
2.2 解説に用いるサンプルパッケージの構成
2.3 作成時の依存関係の管理にpipを用いるケース
2.4 作成時の依存関係の管理にpoetryを用いるケース
第3章 配布パッケージの配布方法とインストール動作方法
3.1 パッケージの配布方法
3.2 パッケージの動作確認(作成手段に依存せず同一)
付録A Pythonにおけるパッケージとは?
付録B 本書で利用するPython環境のインストール方法
B.1 WindowsでのPython環境の作り方
B.2 LinuxでのPython環境の作り方
付録C パッケージ化の前にソース難読化を実施(Pyarmor)
C.1 Pyarmorパッケージのインストール方法
C.2 Setup()関数による配布パッケージの作成手順
C.3 poetryコマンドによる配布パッケージの作成手順
付録D 配布パッケージ化をGitHub Actionsで自動化(CI構築)
付録E Python配布パッケージをGitHubリポジトリで配布する方法
E.1 GitHubのPublicリポジトリに配布パッケージを配置する方法とインストール手順
E.2 GitHubのPrivateリポジトリに配布パッケージを配置する方法とインストール手順
付録F Python配布パッケージをPyPIリポジトリで配布する方法
F.1 配布パッケージを、PyPI公開用に整える
F.2 PyPIアカウントを作成(初回のみ)
F.3 PyPIへのAPIトークンを生成(アクセス範囲ごとに初回のみ)
F.4 配布パッケージをアップロードする
F.5 インストールを確認する
付録G PyPIへのアップロードをGitHub Actionsで自動化する(CI構築)
G.1 ワークフローに、アップロード処理をジョブとして追加
G.2 ワークフローを、PyPIに対してTrusted Publisherとして設定
付録H 参考書籍、参考サイト
あとがき

はじめに

 他のプログラミング言語の経験がある方がPythonへ入門する際に、「Pythonでコードを配布する方法は?」「『パッケージ』という言葉が指すものはNode.jsと同じなの?」などのプログラミング言語間の扱いの違いに戸惑いを覚えたことはないでしょうか?

 本書は、作成したPythonのコードを「他の環境に持って行って実行する」という観点で、依存関係を含めて容易に他環境へインストールするための配布用ファイル形式の作り方、を解説します。Node.jsであれば、次のような作業を行う場面でPythonならどうするか?という話となります。


 1.ルートにindex.jsを作成し、パッケージとして公開したい関数orクラスをexportする

 2.npmコマンドでパッケージを作成する

 3.npmコマンドでパッケージをインストールして、提供された関数orクラスの機能を利用する


 今しがた用いてきた『パッケージ』という言葉もそうですが、用語のいくつかはプログラミング言語によって定義(指す対象)が一般に異なります。また、歴史的経緯により、現状のPythonでは配布用ファイルの作り方が複数用いられています。これらを踏まえて「他のプログラミング言語の経験はあるが、Python言語は初めて」という方向けに、配布用ファイル形式の作り方を3種類と、その際の理解に必要なPythonでの用語の定義を解説します。

本書で解説することと、解説しないこと

 本書は次のことを目的とします。


 ・作成したPythonコードをまとめて、pipコマンドで依存関係も含めてインストールできる配布用ファイル形式として作成できること

 ・作成したファイルをインターネット越しに配布する方法の種類を理解し、そして実際に配布できること


 本書の想定する読者は次の方です。


 ・他の言語でのプログラミング経験はあるが(たとえばNode.jsなど)、Python言語にはあまり馴染みがない方

 ・作成したPythonのコードを開発環境とは異なる環境へ提供して(配布して)、動作させたい方

 ・配布パッケージファイル(Wheelファイル)は存じており、作成方法もひとつは知っているが他の方法も知りたい方


 本書で解説するのは次の内容です。


 ・配布用のファイル作成の手順の理解に必要な用語と操作の概念

 ・配布用のファイル形式の作成に必要な各ファイル作成のPython言語における立ち位置と、依存関係の設定を含めた具体的な作成手順

  ─Pyarmorを用いてコードの難読化してから含める方法も付録で解説します

  ─GitHub Actionsを用いて作成を自動化する方法も付録で解説します

 ・作成した配布用のファイルをインストールした環境での、提供した関数の動作確認手順

  ─ファイルをコピーするなどして提供先のローカルに配置して、そこからのインストールする想定です

 ・作成した配布用のファイルをネットワーク経由で配布する方法

  ─PyPI(npm等に相当)とGitHubのリポジトリを用いる方法を、付録にてそれぞれ簡単に解説します


 本書で解説しないことは次の内容です。


 ・Python言語によるプログラミング方法そのもの

 ・依存関係を管理する方法や配布手段におけるベストプラクティス

 ・PyPIにおける配布の仕組みそのもの

 ・GitHubリポジトリ、GitHub Actions自体の使い方


 なお本書で解説する内容は、Pythonの解説書籍やPython公式を含むWebサイトを参照することで取得可能です。しかし、Python初心者がそれらの情報にたどりつくのは「検索方法がわからない」、「複数を渡り歩く必要がある」ことから容易ではなく労力がかかると考えます。本書は、それらの手間暇を軽減することを目的とします。

サンプルコードについて

 本書でのサンプルの記載は、多くの場合はキーとなるコード部分の抜粋となります。サンプルコードの全体は次のサポートページにて公開しています。実際に動作確認を行う際には、そちらのソースコードを利用してください。

 ・https://github.com/hoshimado/book-python-packaging-intro

動作確認環境

 ・Windows 10

  ─Python 3.11.5

 ・Ubuntu 22.04(Docker on WSL2内)

  ─Python 3.9 (python:3.9-alpine3.18)

免責事項

 本章中のスクリーンショットや利用ライブラリのバージョンは、2023/10/31現在のものです。その後に変更されている場合があります。

 本書に記載された内容は、情報の提供のみを目的としています。したがって、本書を用いた開発、製作、運用は、必ずご自身の責任と判断によって行ってください。これらの情報による開発、製作、運用の結果について、著者はいかなる責任も負いません。

表記関係について

 本書に記載されている会社名、製品名などは、一般に各社の登録商標または商標、商品名です。会社名、製品名については、本文中では©、®、™マークなどは表示していません。

第1章 パッケージ作成の前提理解

 本章では、Pythonのパッケージ周りに初めて触れる前提で、Pythonの配布用ファイル作成の理解に必要な用語と概念を解説します。

1.1 PEPとは?PyPAとは?

 Pythonの言語仕様や推奨される規則、その仕様に至った歴史、論理的根拠などを記録した設計文書のことを「PEP」と呼称します1。PEPはPython Enhancement Proposalの略です。Pythonの実装は「PEP xxxに準拠した実装」などのように行われています。簡単に言えば「PEPは、Pythonインタプリタが従うべき仕様書」となります。Pythonインタプリタの仕様のみでなく、Python言語として推奨コーディング規約などもPEPで定められています2

 Pythonで作成したコード一式を配布する際は、パッケージングを行い配布パッケージの形にまとめます(この後で改めて説明します)。このようなPythonでのパッケージと配布のエコシステムの標準仕様を策定、管理しているワーキングループを「PyPA」と呼称します。PyPAはPython Packaging Authorityの略です3

1.2 モジュールとは?パッケージとは?

 Pythonで書かれた単一の*.pyファイルを「モジュール(Module)」と呼称します4。より正確には、「Pythonにおけるコードの再利用性の基本単位」として定義され、「Pure Module」5と「Extension Module」6の2種類に分かれますが、本書では以降「Pure Module」のことを指して「モジュール」と呼称します7

 複数の「モジュール」を集約したディレクトリのことを「パッケージ」と呼称し、「パッケージ」を配布用に整えたものを「配布パッケージ」(もしくは「配布用のパッケージ」)と呼称します8

 以降、本書ではモジュール、パッケージ、配布パッケージ、と括弧書きを付けずに記載します。

1.3 pipとは?wheelファイル形式とは?

 配布パッケージを取得してインストールする際には、Python標準に含まれているpipコマンド9が一般に利用されます。pipは「パッケージ管理システム」のひとつです。特に指定がない場合は、pipコマンドはWheelファイル形式10の配布パッケージを選好します11。Wheelファイル形式の配布パッケージを用いると、利用者は特別なコンポーネントの構築ツールや経験を必要とせずに対象のパッケージを自身の環境で利用できます。Pythonで用いられる配布パッケージの形式はいくつか存在しますが、本書では以降で特に断らない場合は、PyPAが推奨するWheelファイル形式を指すものとします12

 本書では、Wheelファイルのフォーマット13自体には踏み込みません。Wheelファイルを作成するためのツールの実行方法と、作成されたWheelファイルをローカルで利用する方法14、の観点で解説します。Wheelファイルをインターネットを通じて配布する方法に興味のある方は、付録E「Python配布パッケージをGitHubリポジトリで配布する方法」と付録F「Python配布パッケージをPyPIリポジトリで配布する方法」で簡単に触れていますので、参照ください。

1.4 仮想環境とは?(依存関係のローカルインストール方法)

 Pythonに標準で含まれているパッケージ以外の、任意のサードパーティー製のパッケージが提供する機能を利用する場面を考えます。機能の例としては、インターネットアクセスを容易にするパッケージである「requests」や、データ処理を(データのクレンジングを)容易にするパッケージである「pandas」、などを用いる場面です。

 これらの機能は、配布パッケージの形式でPyPIにて公開されているので、pipコマンドを用いて自身の利用環境へ簡単に追加できます(パッケージをインストールできます)。pipコマンドを単純に実行すると、対象パッケージはグローバル環境にインストールされます。そうすると、アプリケーションAではパッケージZのVersion 1.0を必要とするが、一方でアプリケーションBではパッケージZのVersion 2.0を必要とする、という場面で困ったことになります。これを解決するために、Pythonでは「Python仮想環境」という概念を利用します(以降、「仮想環境」と略す。とくに断らない限りPythonの仮想環境を指す)。標準に含まれない追加のパッケージをインストールする際には、必須ではありませんが仮想環境を構築してからインストールすることが推奨されます15

  

 仮想環境を作成して、「その環境の中で」pipによるパッケージのインストールとアプリケーションを実行することで「アプリケーション固有の隔離された環境で実行」できます。仮想環境はそれ自身のインストールディレクトリを持ち、他の仮想環境とライブラリを共有しません。これにより、グローバル環境を汚さずにアプリケーションの動作に必要なパッケージの依存関係をアプリケーション単位でインストールできます。

 現在、次のふたつのPython仮想環境を構築するためのツール(パッケージとして提供)がよく知られています。


 ・venv

 ・virtualenv


 venvパッケージはvirtualenvのパッケージのサブセットであり、Pythonに標準で含まれているパッケージであり、pipコマンドによる追加インストールなしに利用できます。

 本書では、利用の簡単なvenvパッケージ(venvコマンド)を用いるものとします。仮想環境の具体的な利用方法は「2.3.1 仮想環境venvの作成」と「2.4.2 仮想環境poetry shellを作成」16で解説します。

1.5 パッケージ作成での推奨フォルダー構成

 配布することを考慮したパッケージを作成する際に、推奨されるフォルダー構成はリスト1.1の通りです。一般にこのような一式をプロジェクトと呼称し、ひとつのプロジェクトではひとつのパッケージを含めます。

リスト1.1: 配布を考慮したパッケージの推奨フォルダー構成

project_root
  +--[パッケージのメタ情報を記述したファイル].xxx
  +--・・・(ビルド方法や依存関係のパッケージなど)・・・
  |
  +--[パッケージ名]/
  |  +--[パッケージを構成するモジュール].py
  |  +--・・・
  |  |
  |  +--__init__.py
  |  +--__main__.py
  |
  +--[パッケージのテストコードなど]
  \--・・・

 リスト1.1は抽象度が高すぎるため、ある程度まで想定場面を絞ったサンプルを用いて、以降では推奨フォルダー構成を解説します。なお、配布パッケージの作成に用いるツールにより若干の差分があるため、実際に動作可能なファイル・フォルダー構成の具体例は、配布パッケージ作成の方式別に解説している第2章を参照ください。

 サンプルとして、「向こう1週間の天気の予想気温を取得する」機能を提供するパッケージ「weatherforecast」を作成する場面を考えます。このパッケージは、次のモジュールをまとめたもの(集約したもの)とします。ファイル名などは本節での限定的なものとします(第2章で用いるサンプルコードより抽象度が高いです)。


 ・天気の予想気温を取得するモジュール「forecast.py

 ・取得した予想気温をインプットとして特性を出力するモジュール「analyse.py


 これらのモジュールを集約したパッケージを作成する際に推奨されるファイル・フォルダー構成例はリスト1.2です17。これは最低限の要素での構成例です。

リスト1.2: 配布を考慮したパッケージのフォルダー構成例

project_root
  +--setup.py or pyproject.toml
  +--README.md
  +--LICENSE.txt
  |
  \--weatherforecast/
     +--forecast.py
     +--analyse.py
     +--__init__.py

 リスト1.2の構成要素は表1.1の通りです。

表1.1: パッケージのファイル・フォルダー構成要素
ファイル・フォルダー名 目的
setup.py or pyproject.toml 配布パッケージ化する際の作業項目を記載したファイル18
README.md パッケージに関する説明を記載したファイル
LICENSE.txt 配布の条件を指定するライセンスファイル(※外部に公開する場合)
weatherforecast/ パッケージ本体であるフォルダー
forecast.py, analyse.py 含めるパッケージに集約したモジュール
__init__.py パッケージとするフォルダーに一般に含めるファイル

 リスト1.1において、次のファイル群は「パッケージのメタ情報を記述したファイル」に該当し、記載の通りの固定のファイル名での構成が推奨されます(変更できないわけではありません)。


 ・setup.py

 ・pyproject.toml

 ・README.md

 ・LICENSE.txt


 上記の他に、必要に応じて「requirements.txt」や「MANIFEST.in」ファイル、また「docs/」フォルダーなどを追加する場合もありますが、説明は割愛します。

  

 リスト1.1においてフォルダーは「パッケージ名」に該当します。


 ・weatherforecast/


 このフォルダー名は任意です。PEP8に記載されている命名規約に沿って、パッケージの目的が分かりやすい名称を付けます19。このフォルダー配下に、パッケージにまとめるモジュール一式を格納します(__init__.py以外のモジュール名も任意です)。

 これらの他に、必要に応じて表1.2のようなフォルダー等を含める場合もありますが、説明は割愛します。

表1.2: その他のフォルダー構成要素の例
フォルダー名 目的
venv/ 仮想環境の格納先(venvコマンドにより自動生成)
tests/ UnitTestコードの格納先
docker/ Dockerプロジェクトの格納先
notebooks/ Jupyter Notebookファイルの保管先
examples/ 使用例(サンプルコードなど)の格納先

推奨フォルダー構成の考え方

 本書は、PyPAの提供する「Python Packaging User Guide」での記載に準じて推奨フォルダー構成を解説しています。その際に、「ゼロから学ぶPython」と「The Hitchhiker's Guide to Python」も併せて参照し、次の方針で修正した(主に簡素化)ファイル・フォルダー構成としてします。


・setup.cfgは、setup.pyの観点からは設定の外部ファイル化なので、説明を簡単にする目的で省略(setup.py側にマージしたケースとした)

・MANIFEST.inは、通常の配布パッケージに含める種類のファイルのみの構成であれば不要となるので、省略

・「ガイド型文書 > パッケージングとプロジェクトの配布」ではsetup.pyでの案内だが、「チュートリアル型文章>Pythonのプロジェクトをパッケージングする」では代わりにpyproject.tomlでの案内のため、両方式を併記


 その上で、本書では仮想環境にvenvパッケージを用いていることを考慮しての補足、「Pytest」での「test layout: Tests outside application code」を参照しての補足を加えています。

 主な参照先のリストは以下です。

・PyPA > Python Packaging User Guide > ガイド型文書 > パッケージングとプロジェクトの配布

 ─https://packaging.python.org/ja/latest/guides/distributing-packages-using-setuptools/

・ゼロから学ぶPython > 4. モジュールとパッケージ > 4.7. プロジェクト構成

 ─https://rinatz.github.io/python-book/ch04-07-project-structures/

・The Hitchhiker's Guide to Python > プロジェクトの構造化

 ─https://python-guideja.readthedocs.io/ja/latest/writing/structure.html

・pytest > Good Integration Practices > Choosing a test layout / import rules

 ─https://docs.pytest.org/en/6.2.x/goodpractices.html

1. PEPの定義は、PEP1で参照できます(https://peps.python.org/pep-0001/)。また、日本語訳はこちらで参照できます。 https://sphinx-users.jp/articles/pep1.html

2. Pythonのコーディング規約は、主にPEP 8で参照できます。 https://pep8-ja.readthedocs.io/ja/latest/

3. "PyPA is a working group that maintains many of the relevant projects in Python packaging.", https://packaging.python.org/en/latest/glossary/ > "Python Packaging Authority (PyPA)"

4. "The basic unit of code reusability in Python, existing in one of two types: Pure Module, or Extension Module.", https://packaging.python.org/en/latest/glossary/ > "Module"

5. "A Module written in Python and contained in a single .py file.", https://packaging.python.org/en/latest/glossary/ > "Pure Module"

6. "A Module written in the low-level language of the Python implementation: C/C++ for Python, Java for Jython. ... e.g. a shared object (.so) file for Python extensions on Unix, a DLL (given the .pyd extension)", https://packaging.python.org/en/latest/glossary/ > "Extension Module"

7. 付録での記載を除きます。付録ではコンパイル済みモジュールも扱うため、Extension Moduleを含めて「モジュール」と呼称します。

8. パッケージと配布パッケージのより詳細な定義は、付録Aを参照ください

9. "pip is the package installer for Python. You can use it to install packages from the Python Package Index and other indexes.", https://pip.pypa.io/en/stable/

10. "A Built Distribution format introduced by an official standard specification, which is intended to replace the Egg format. Wheel is currently supported by pip.", https://packaging.python.org/en/latest/glossary/ > "Wheel"

11. "pipは互換性のあるwheelを選好します", https://packaging.python.org/ja/latest/tutorials/installing-packages/ > "ソースコード配布物 vs. Wheels"

12. "The official binary distribution format for Python.", https://github.com/pypa/wheel

13. Wheelファイルをごく簡単に説明すると、パッケージの動作に必要な依存関係などのメタ情報、ビルド済みのモジュール(Extension Module)を含めたパッケージの構成ファイル、などの一式を固めたzipファイルのことです。 https://packaging.python.org/ja/latest/specifications/binary-distribution-format/

14. ローカルに配置した配布パッケージを直接指定してインストールする利用方法、という意味です。なお、pipコマンドで特に指定しなかった場合、通常はPyPIが提供するリポジトリに配置された配布パッケージを参照しにいきます。

15. "必須ではないが、仮想環境を構築する", https://packaging.python.org/ja/latest/tutorials/installing-packages/

16. Poetryも仮想環境として内部的にvenvを利用しており、そちらへ依存パッケージをインストールします("Python Poetry: Package and venv Management Made Easy") https://python.land/virtual-environments/python-poetry

17. このフォルダー構成を推奨する根拠はコラム「推奨フォルダー構成の考え方」を参照ください

18. 過去はsetup.pyを用いるのが一般的であったが、最近はpyproject.toml利用への推奨へ変わりました。現時点では両方とも未だ使われているため、併記します。詳細は「2.1 配布パッケージ作成ツールの種類」を参照ください。

19. すべて小文字で表現します。短い名称が望ましいです。アンダースコアの使用は推奨されませんが、可読性の向上の目的においてその限りではありません。 https://peps.python.org/pep-0008/ > "Package and Module Names"

試し読みはここまでです。
この続きは、製品版でお楽しみください。