Python におけるパッケージングに関する概要#

汎用プログラミング言語として Python は数多くの用途に使えるように設計されています。ウェブサイト構築にも産業用ロボットにもあなたが友達と一緒に遊ぶゲームにももっと他の用途にも、同じコア技術が使えるのです。

Python は自由度が高いので、プロジェクトの利用者について、また、それに対応してプロジェクトが動作するであろう環境について、すべての Python プロジェクトにおいて最初に考えなければなりません。コードを書く前にパッケージングについて考えておくというのは奇妙に見えるかもしれませんが、この作業こそが将来の頭痛の種を摘み取るという驚くべきことを起こすのです。

この概要文書は、 Python の過剰とも言える多数のパッケージング手段からどれを選択するかについての汎用の決定木を提供します。読み進めて、あなたの次のプロジェクトにとっての最適解を選んでください。

デプロイメントについて検討する#

パッケージはインストールされる(あるいは 配置 される)ために存在しているので、なにかをパッケージ化する前に次のような配置のための質問にいくらかの答えを持っておきたいと思うでしょう:

  • あなたのソフトウェアのユーザはどんな人たちでしょうか?ソフトウェアを開発する他の開発者たちがインストールするのでしょうか、データセンタでオペレーションをする人々でしょうか、それとも、ソフトウェアを知り尽くしているとは言えないような人たちでしょうか?

  • あなたのソフトウェアは、サーバ上で走らせることを想定していますか、それとも、デスクトップ、モバイル端末 (携帯電話やタブレット端末等) 、あるいは、専用端末に組み込む形で?

  • あなたのソフトウェアは、単独でインストールされるものですか、それとも、巨大なデプロイメントバッチの一部として?

パッケージングとは、インストール先となる環境と配置(デプロイ)経験に関わるすべてのことです。上に述べた質問には多くの回答があり、それぞれの事情の組み合わせごとに解決策が存在します。この情報とともに、以下の概要説明の中で、あなたのプロジェクトに最適なパッケージング技術についてご案内します。

Python のライブラリやツールをパッケージングする#

PyPI や setup.pywheel ファイルについて聞いたことがあるかもしれません。これらは Python のソースコードを開発者に配布するための Python エコシステムのほんの一部で、これらについては パッケージングとプロジェクトの配布 に説明があります。

パッケージングに関する以下のアプローチは、開発環境における技術に明るい聞き手が用いるライブラリやツールを念頭に置いています。技術にあまり明るくない聞き手向けに Python をパッケージする方法や、製品使用環境での方法を探している場合は、 アプリケーションをパッケージングする まで飛ばしてください。

Python モジュール#

標準ライブラリだけに依存している Python のファイルは、再配布して再利用することができます。他には正しいバージョンの Python 用に書かれていることと、標準ライブラリだけに依存していることを確実にしておけば良いでしょう。

この方法は、単純なスクリプトやスニペットを互換性のあるバージョンの Python を持っている人たちどうしで (電子メールや StackOverflow や GitHub gists などで) 共有するには優れた方法です。例えば bottle.pyboltons のように、 Python ライブラリ全体をこのやり方で共有することをオプションの一つとして提供しているものさえあります。

しかしながら、複数のファイルで構成されるプロジェクトや追加のライブラリを必要とするもの、また、特定バージョンの Python を必要とするものには適用できず、その場合には下のようなやり方が選択肢になります。

Python ソースコード配布物#

あなたのソースコードが複数の Python ファイルでできているなら、ディレクトリ構造の中に整理してあるのが普通です。 Python ファイルを置いてあるディレクトリならどれでも、 パッケージインポート ができるはずです。

パッケージは複数のファイルで構成されるので、その配布がやや難しくなります。ほとんどのプロトコルではたった一個のファイルしか一度に送ることができません (リンクをクリックしたら複数のファイルをダウンロードしたことあります?)。不完全な転送になってしまうことは容易く、送り先でソースコードの完全性を保証することは困難です。

あなたのソースコードが純粋な Python コード以外は何も含んでいない間は、そして、配置先の環境であなたが想定しているバージョンの Python が動作することを知っていれば、 Python 由来のパッケージングツールを使って ソースコード 配布パッケージ もしくは 短縮系で*sdist* を使えば良いでしょう。

Python の sdists は圧縮済みのアーカイブ (.tar.gz ファイル) で、ひとつかそれ以上のパッケージないしモジュールを内包しています。もしあなたのソースコードが純粋に Python だけで書かれていて、他の Python パッケージに依存しているだけなら、 ソースコード配布物フォーマット 仕様を見ればもっと詳しく知ることができます。

もし非 Python のソースコード、あるいは、非 Python のパッケージ (lxml における`libxml2 <https://en.wikipedia.org/wiki/Libxml2>`_ や、numpy における BLAS ライブラリなど) に依存しているなら、純 Python で書かれたライブラリにとっても多くの利点がある、次の節で詳細に説明されるフォーマットを使う必要があるでしょう。

注釈

Python と PyPI は、同一のパッケージの異なる実装を提供する複数の配布物をサポートしています。例えば、もはや保守されてはいないが先駆的で重要な PIL 配布物 が PIL パッケージを提供しているし、 PIL からフォークして今も活発に保守されている Pillow も同様です!

この Python パッケージングの素晴らしいパワーで、あなたのプロジェクトの install_requiresrequirements.txt を変更するだけで Pillow が PIL に対して単純に入れ替えるだけで済む代替物になっているのです。

Python バイナリ配布物#

Python の実際的な力の多くは、ソフトウェアのエコシステム、とりわけ C ・ C++ ・ Fortran ・ Rust ・その他の言語で書かれたライブラリと統合できる能力からもたらされます。

このようなコンパイルを必要とする言語で書かれた部品をビルドするのに適切なツールや経験をすべての開発者が持っているわけではないので、ライブラリをコンパイル済みの状態で出荷するように設計された Wheel を Python は作りました。実際に、 Python のパッケージインストーラである pip は、インストールが素早くできるので常に wheel ファイルを選好するし、純 Python のパッケージでさえも wheel ファイルの方がうまく動作します。

バイナリ配布物は、対応するソースコード配布物と一緒に配布されるのが最良です。 あらゆるオペレーティングシステム用のソースコードの wheel ファイルをアップロードしていないとしても、sdist をアップロードすることで他のプラットフォームのユーザたちがビルドすることができるかもしれません。あなたが極めて特殊なユースケース向けにプログラムを作成していて、受け取る人たちがいずれか一方しか必要としないことを熟知しているので ない限り 、 sdist と wheel の両方を一緒に公開することをデフォルトにしてください。

Python と PyPI を使えば、wheel ファイルと sdist ファイルを一緒にアップロードするのが簡単になります。 tutoeials/packaging-projects のチュートリアルに従うだけです。

ツールやライブラリ向けの Python のパッケージング機能の概要。

Python が推奨するライブラリやツールをパッケージングする技術。パッケージングの変遷 (2017) から抜粋。#

Python アプリケーションをパッケージングする#

ここまで、 Python に元々組み込まれている配布ツールについてだけ議論してきました。この導入部分に基づいて、これらのビルトインされたアプローチが Python のある環境だけを対象にしたもので、聞き手は Python パッケージのインストール方法を知っているものと推測するのは正しいでしょう。

多様なオペレーティングシステム・設定・そこに居る人々を想定すると、聞き手が開発者である場合にだけこの仮定が正当であると言えます。

Python に元々組み込まれているパッケージング機能は、ほとんどの場合には、開発者間で再利用可能なソースコードや呼び出されるライブラリを配布するために作られています。 setuptools のエントリポイント のような技術を用いることで、 Python の packaging ライブラリの上に構築されている ツール類 や開発者向けの基本的なアプリケーションに便乗することができます。

ライブラリは部品であって完成したアプリケーションではありません。アプリケーションを配布するには、全く新しい技術の世界が広がっています。

ここからのいくつかの節では、ターゲットとなる環境への依存関係に従ってこのようなアプリケーションをパッケージングする選択肢を整理し、あなたのプロジェクトに最適なものを選択できるようにしましょう。

フレームワークに依存する#

ウェブサイトのバックエンドやその他のネットワークサービスのような、いくつかの種類の Python アプリケーションでは、その開発とパッケージングを可能にするフレームワークが存在することは極めてありふれたことです。動的ウェブのフロントエンドやモバイルクライアントのような他の種類のアプリケーションはとても複雑で、フレームワークが単に便利という以上の存在になっています。

これら全てのケースで、フレームワークのパッケージングと配置の物語から振り返ってみるのが妥当でしょう。いくつかのフレームワークは、このガイドの残りの部分で概要を描き出す技術を内包する配置システムを含んでいます。このような場合には、最も簡単で最も信頼できる製品レベルの経験を積むまで、あなたのフレームワークのパッケージングガイドを延期しておきたくなるでしょう。

このようなプラットフォームやフレームワークが内部でどのように動作しているのかと不思議に思うのであれば、いつでもその先の節を読めば良いでしょう。

サービスプラットフォーム#

"Platform-as-a-Service" もしくは "PaaS" 上で開発を行っているのであれば、当該 PaaS のパッケージガイドに従う方が良いと思うようになることでしょう。このようなタイプのプラットフォームは、彼らの流儀に従っている限りはパッケージングやデプロイメントの面倒を見てくれます。後述する他のすべてのオプションが存在するので、ほとんどのソフトウェアはこれらのテンプレートのひとつにはうまく合致しません。

自分の機材やユーザのパーソナルコンピュータやその他の機材に配置することを想定するソフトウェアを開発しているのであれば、このまま読み進めてください。

ウェブブラウザとモバイルアプリケーション#

Python は着実に前進して新しい世界に突入しています。最近では、モバイルアプリやウェブアプリケーションのフロントエンドを Python で書くことができるようになっています。言語自体には慣れていても、パッケージングや配置の実務は全く新しいものになっています。

このような新しい未開拓分野でリリースを計画しているのであれば、以下のフレームワークに興味が湧いて、それぞれのパッケージングガイドを参照したくなるかもしれません。

フレームワークやプラットフォームに興味がなければ、あるいは、上記のフレームワークが利用している技術や手練手管について不思議に思うのであれば、このまま読み進めてください。

インストール済みの Python に依存する#

任意のコンピュータを選んだ時に、もちろんその環境にもよりますが、 Python が既にインストールされている確率は相当に高いでしょう。 Linux や Mac オペレーティングシステムではもう多年にわたってデフォルトでインストールされているので、データセンタの機材や、開発者やデータ科学者の個人用の機材には Python が入っているものと思っても構わないでしょう。

このモデルを支える技術:

  • PEX (Python EXecutable)

  • zipapp (依存関係を管理する助けにはならない。Python 3.5+ が必要。)

  • shiv (Python 3 が必要)

注釈

ここでのすべてのアプローチでは、ほとんどのインストール先となる環境にインストール済みの Python があるものと当てにしています。もちろん、これは、一桁メガバイト規模やさらにはキロバイト規模の最小のパッケージを作ることになります。

一般に、インストール先の環境に対する依存を減少させるとパッケージ側のサイズは大きくなるので、ここで述べる解決策は、おおまかに出力となるパッケージのサイズの増える順番に整理しています。

個別のソフトウェア配布エコシステムに依存する#

長い間、Mac や Windows を含むさまざまなオペレーティングシステムは、組み込みのパッケージ管理システムを欠いてきました。ごく最近になって、これらの OS にも所謂「アプリストア (app stores)」が追加されましたが、しかし、まだ消費者向けのアプリケーションを扱っているだけであり、開発者の役に立つものは少ないのが現状です。

長い間、開発者が解決方法を探し求めてきており、この格闘の中から Homebrew のような独自のパッケージ管理手法が勃興した。 Python 開発者にとっての最も適切な代替方法は、 Anaconda と呼ばれるパッケージエコシステムです。 Anaconda は Python を中核として作成されており、学術や分析やデータ主導の環境でより一層一般的になってきていて、サーバ中心の環境に さえ入り込んでいます。

Anaconda エコシステム向けにビルドし公開するための指示書き:

よく似たモデルが Python 配布物の代替物をインストールする際にも適用されますが、オペレーティングシステムレベルのパッケージはサポートしていません。

自分の Python 実行形式を持ち込む#

我々が知るところのコンピューティングは、プログラムを実行する能力として定義されます。それぞれのオペレーティングシステムは、そのまま実行することが可能なひとつかもっと多くのプログラムフォーマットを元々サポートしています。

そのようなフォーマットにあなたの Python プログラムを変換する数多くの手練手管や技術が存在していて、そのほとんどでは Python インタープリタやその他の依存先を単一の実行形式のファイルに組み込むことになるでしょう。

フリージング と呼ばれるこの方法論は、しばしば複数の技術と共にかなりの努力を要求しますが、幅広い互換性と継ぎ目のないユーザ経験を提供します。

Python フリーザの選択肢:

上記のものはほとんどが単独のユーザでの配置です。複数部分から構成されるサーバアプリケーション向けには Chef Omnibus を見てください。

自分自身のユーザスペースを持ち込む#

オペレーティングシステム -- Linux や Mac OS や Windows を含む -- で、しばしば オペレーティングシステムレベルの仮想化 もしくは コンテナ化 として参照される相対的に新しい手法を用いた、軽量のイメージとしてパッケージされたアプリケーションを走らせるように設定することができるものが数を増しています。

このような手法は Python 単体もしくは Python パッケージではなく OS のファイルシステム全体をパッケージ化するので、ほとんどの場合には Python を直接にサポートしているわけではありません。

(訳注、このような技術の) 取り入れが最も広範囲に渡るのは、この技術の発祥の地であり下に述べる技術が最もうまく動作する Linux サーバです:

自分自身のカーネルを持ち込む#

ほとんどのオペレーティングシステムでは、何らかの形であるオペレーティングシステム全体を内包するイメージの形にパッケージされたアプリケーションを動作させることができるような、古典的な仮想化がサポートされています。このような仮想マシンもしくは VM を動作させることは枯れた方法論で、データセンタ環境に広く普及しています。

複雑なアプリケーションの中にはこのパッケージング方法から利益を得るものもありますが、このような手法はたいていの場合はデータセンタにおけるかなり大規模な配置のために使用します。技術としては Python を直接サポートしているわけではなく、次のものを含みます:

自分自身のハードウェアを持ち込む#

最もすべてを包含した方法は、あなたのソフトウェアを何らかのハードウェア上にインストールして出荷することです。この方法では、あなたのソフトウェアのユーザは電力供給しか要求されません。

上で述べた仮想マシンがもっぱら技術に明るい人向けであるのに対し、ハードウェアによるアプライアンス機器は最先端のデータセンタから最も若い子供たちまでの誰にでも使えます。

AdafruitMicroPython 、あるいは、もっとパワーのあるハードウェアで Python が動作するものにあなたのプログラムを組み込んで、データセンタやあなたのユーザの家に出荷しましょう。彼らはプラグアンドプレイで使うし、あなたはその日の仕事を終わりにできるでしょう。

Python アプリケーションをパッケージするのに使われる技術の概要。

Python アプリケーションをパッケージするのに使われる技術の単純化された全体像。#

これは何...#

上記の節ではかなり要約して書いているので、飛躍している点が目につくかもしれません。

オペレーティングシステムレベルのパッケージ#

上記の 個別のソフトウェア配布エコシステムに依存する で言及したように、オペレーティングシステムの中には独自のパッケージ管理機構を備えているものがあります。あなたがターゲットにするオペレーティングシステムが非常にはっきりわかっているなら、 deb (Debian や Ubuntu その他向け。) か、 RPM (Red Hat や Fedora その他向け。) のようなフォーマットを直接利用して、インストールや配置さえもその面倒を見るのに組み込みのパッケージ管理機構を活用することができます。 FPM を使えば、同じソースコードから deb と RPM の両方を生成することさえ可能です。

ほとんどの配置パイプラインでは、 OS パッケージ管理機構は全体から見ればほんの一部です。

virtualenv#

Virtualenvs は、複数世代の Python 向けに開発をする者にとっては以前から避けられないツールであり続けてきたが、高レベルのツール群がラップするようになったので徐々に見えなくなりつつあります。特にパッケージングの観点では、共に virtualenvs を内包する形でラップしている the dh-virtualenv toolosnap では virtualenvs はプリミティブとして使われています。

開発環境ではありがちですが、商用環境への配置ではインターネットから virtualenv への python -m pip install を走らせることに信用をおいてはなりません。上に述べた概要には、より良い解決策がたくさんあります。

セキュリティ#

あなたのパッケージの部品を更新することは、ここまで積み上げてきたものよりさらに困難なものになるでしょう。あらゆるものがより緊密に互いに固着しているのです。

例えば、仮にあなたがコンテナ型の仮想環境を配置していて、カーネルのセキュリティ問題が発生したとすれば、アプリケーションに新たなビルドを要求することなくホスト側のカーネルが更新されるかもしれません。もしあなたが VM イメージを配置しているなら、それを再ビルドする必要があるかもしれません。このような動的な挙動をよりセキュアにするひとつのオプションは、以前から少々議論の的になっているがまだ決着のついていない 静的リンク対動的リンク ということになります。

まとめ#

Python におけるパッケージングは、凸凹道を車で行くようなもので苦労が多いという評判も少しあります。このような感想は、ほとんどの場合は Python が多用途に使えることの裏返しです。それぞれのパッケージング方法の間にある自然な境界線を理解しさえすれば、さまざまに異なる風景が、もっともバランスが取れていて自由度の高い言語を使うということのために Python プログラマが支払う小さな代償であることに気づくことでしょう。