オープンソース・プロジェクトを成功させる上で中心となるのは、パッケージ化です。そして適切なパッケージ化をするための重要な要素はバージョン管理にあります。プロジェクトはオープンソースであるため、パッケージを公開し、オープンソース・コミュニティーによる多くのメリットを実現したいものです。パッケージ化のメカニズムはプラットフォームや言語によって異なりますが、この記事では特に Python と Python のパッケージ化エコシステムに焦点を絞ります。この記事では、パッケージ化のメカニズムについて説明し、それを基礎として発展させられるようにします。また、即座に作業を始められるように実践的な例を示します。
パッケージ化することは単に適切であるというだけではありません。ソフトウェアをパッケージ化する理由として、以下の 3 つの実用的な理由が挙げられます。
- 使いやすさ
- (バージョン管理による) 安定性
- ディストリビューション
アプリケーションのインストールを可能な限り容易にすることは、ユーザーに対する配慮です。パッケージ化することにより、ソフトウェアが扱いやすくなり、インストールも容易になります。インストールが容易であれば、ユーザーはそのソフトウェアを容易に使い始めることができます。パッケージを
PyPI (Python Package Index) に公開すると、pip や easy_install などのユーティリティーを利用してそのパッケージを容易に利用できるようになります (これらのツールについては「参考文献」のリンクを参照)。
また、ソフトウェアのパッケージをバージョン管理して提供することで、そのソフトウェアのユーザーが自らのプロジェクトにおいて依存関係を指定する際に、そのソフトウェアの特定のバージョンに対する依存関係として指定できるようになります。例えば Pinax のバージョンとして 0.9a2.dev1017 を指定するには以下のように表現します。
Pinax==0.9a2.dev1017 |
このように指定すると、そのプロジェクトで Pinax の 0.9a2.dev1017 リリースを使用するように強制することができます。
インターフェースが大幅に変わるような変更を後でリリースした場合にも、バージョン管理によって高い安定性を保証することができます。バージョン管理により、ユーザーは自分が入手しているものを正確に知ることができ、またリリース間の違いを容易に追跡することができます。さらに、プロジェクトの開発者は、どのバージョンを対象にコーディングを行っているのかを正確に知ることができます。
PyPI (または独自の配布サーバー) にパッケージを公開するための一般的な方法として、ソース・ディストリビューションを作成してアップロードする方法があります。ソース・ディストリビューションはプロジェクトのソースを配布可能な単位としてパッケージ化するための標準的な手段です。バイナリー・ディストリビューションを作成する方法もありますが、オープンソースであるためにはソースも配布するのが妥当です。ソース・ディストリビューションを作成すると、インターネット上のソフトウェアを検索、ダウンロードして自動インストールするツールを利用しやすくなります。このプロセスにより、ソフトウェアをローカルで開発する場合の作業が容易になるだけではなく、ソフトウェアのデプロイメントも容易になります。
つまり、ユーザーにとってソフトウェアの統合とインストールが容易になるようにし、信頼できるバージョン指定が可能になるような適切なバージョン管理手法を使用し、より広く配布されるようにパッケージを公開することで、そのプロジェクトが成功して広く採用されるようになる可能性が一層高まるはずです。プロジェクトが広く採用されると、より多くのコントリビューターが得られる可能性につながります。それはすべてのオープンソース開発者が間違いなく望むことです。
setup.py スクリプトの目的の 1 つは、ソフトウェアをパッケージ化して配布サーバーにアップロードするための実行可能ファイルとして機能することです。よく使われる Python リポジトリーを見るとわかるように、setup.py スクリプトの内容はそれぞれ大幅に異なります。この記事では setup.py の基本部分に焦点を絞ります。さらなる詳細について探るには「参考文献」セクションを参照してください。
setup.py ファイルを使用すると、多種多様なタスクを実行することができますが、ここでは以下のコマンドを実行できるようにするための setup.py ファイルを作成します。
python setup.py register python setup.py sdist upload |
最初のコマンド register は setup.py スクリプト内にある setup() 関数から情報を取得し、このパッケージのエントリーを PyPI
に作成します。このコマンドは何かをアップロードするわけではなく、プロジェクトに関するメタデータを作成し、後で PyPI
にリリースをアップロードしてホストできるようにします。次の 2 つのコマンドは連結されており、sdist upload はソース・ディストリビューションをビルドし、PyPI にアップロードします。ただしその前に、.pypirc 構成ファイルを設定したり、実際に setup.py の内容を作成したりするなどの前提となる作業がいくつかあります。
まず、.pypirc
ファイルを構成します。このファイルはホーム・ディレクトリーに配置されている必要がありますが、ホーム・ディレクトリーの場所はオペレーティング・システムによって異なります。UNIX、Linux、Mac
OS X の場合には、cd ~/ と入力するとホーム・ディレクトリーに行くことができます。.pypirc ファイルには
PyPI に対するクレデンシャルが含まれている必要があります (リスト 1)。
リスト 1. 典型的な .pypirc ファイル
[distutils]
index-servers =
pypi
[pypi]
username:xxxxxxxxxxxxx
password:xxxxxxxxxxxxx
|
次に、PyPI にアクセスし、アカウントを登録します (無料ですので心配ありません)。PyPI に登録する際に作成したものと同じユーザー名とパスワードを .pypirc ファイルに記載し、pypirc ファイルの名前を必ず ~/.pypirc にします。
ここで、setup.py スクリプトを作成するためには、PyPI の index ページに表示する内容と、プロジェクトの名前を決める必要があります。最初に、私がさまざまなプロジェクトに使用している setup.py 用のテンプレートをコピーします (リスト 2)。インポート命令と関数をスキップしてテンプレートの一番下に注目し、皆さんのプロジェクトに合わせて何を変更する必要があるのかを見てください。完全なスクリプトへのリンクは「参考文献」に挙げてあります。
リスト 2. setup.py テンプレート
PACKAGE = ""
NAME = ""
DESCRIPTION = ""
AUTHOR = ""
AUTHOR_EMAIL = ""
URL = ""
VERSION = __import__(PACKAGE).__version__
setup(
name=NAME,
version=VERSION,
description=DESCRIPTION,
long_description=read("README.rst"),
author=AUTHOR,
author_email=AUTHOR_EMAIL,
license="BSD",
url=URL,
packages=find_packages(exclude=["tests.*", "tests"]),
package_data=find_package_data(
PACKAGE,
only_in_packages=False
),
classifiers=[
"Development Status :: 3 - Alpha",
"Environment :: Web Environment",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Framework :: Django",
],
zip_safe=False,
)
|
まず、このテンプレートではプロジェクトに 2 つの異なるファイルがあると想定していることに注目してください。1 つ目のファイルは long_description のために使用されています。このファイルは setup.py と同じディレクトリーにある
README.rst ファイルの内容を読み取り、その内容をストリングとして long_description
パラメーターに渡します。このファイルが PyPI
のランディング・ページに内容を追加します。そのため、このファイルの中でプロジェクトについて簡単に説明し、使い方の例を示すのは良い考えです。2 つ目のファイルはパッケージの __init__.py ファイルです。ここに明示的に記述されているわけではありませんが、VERSION 変数を設定する行によってパッケージがインポートされます。そしてパッケージがインポートされる際、Python は __init__.py ファイルを必要とし、そのモジュールの中で __version__ という変数が定義されていることを想定します。ここでは、この変数をストリングとして設定します。
# __init__.py __version__ = "0.1" |
では、入力の他の部分を見てみましょう。
- PACKAGE はプロジェクトの中にある Python パッケージです。PACKAGE は __init__.py モジュールを含む最上位レベルのフォルダーであり、setup.py ファイルと同じディレクトリーになければなりません。例えば以下のような構成でなければなりません。
/- |- README.rst |- setup.py |- dogs |- __init__.py |- catcher.py
つまりこの場合は
dogsがパッケージです。 - NAME は通常、PACKAGE 名と似ているか PACKAGE 名と同じですが、任意の名前で構いません。人々がそのソフトウェアを呼ぶ際の名前が NAME
であり、そのソフトウェアは NAME という名前で PyPI に表示されます。そしてもっと重要な点として、ユーザーは NAME という名前のソフトウェアをインストールします
(例えば
pip install NAMEなど)。 - DESCRIPTION はプロジェクトの簡単な説明にすぎません。1 文による説明で十分です。
- AUTHOR と AUTHOR_EMAIL は文字どおり作成者の名前と E メール・アドレスです。この情報はオプションですが、そのプロジェクトに関して作成者に連絡を取りたい人のために E メール・アドレスを含めておくことは適切なプラクティスです。
- URL はプロジェクトの URL です。この URL はプロジェクトの Web サイトや Github リポジトリー、その他任意の URL で構いません。この URL の情報もオプションです。
また、ライセンスや分類情報を提供することもできます。setup.py ファイルを作成するための詳細については Python のドキュメントを調べてください。(「参考文献」を参照。)
バージョン管理はそれだけで 1 つのトピックになりますが、ここではパッケージ化のコンテキストにおけるバージョン管理について説明しておきます。というのも、適切なパッケージ化には適切なバージョン管理が必要だからです。バージョン管理はユーザーとのコミュニケーションの 1 つの形です。バージョン管理をすることで、ユーザーは高い安定性と信頼性を持った成果物を作成できるようになります。さらにはバージョン管理を通じて、ユーザーには何かを変更したことを伝えることになり、変更が行われた箇所に関して明示的な境界を設けることになります。
Python パッケージのバージョン管理に関する標準は PEP (Python Enhancement Proposal) 386 に記述されています (「参考文献」を参照)。この標準には実用的なルールが詳細に説明されています。PEP を読んで理解していなくても、さらには PEP に同意しない場合であっても、PEP に従った方が賢明です。PEP を見慣れている Python 開発者が次第に増えているからです。
また、バージョン管理は単に安定したリリースを PyPI にアップロードするためのものではなく、devNN 接尾辞を使用して dev
リリースを作成する場合にも便利です。通常は、開発版を PyPI にアップロードするのは適切ではありませんが、パブリックな (またはプライベートな)
配布サーバーを独自にセットアップすることによって開発版を公開することは可能です。そうすれば、最新の開発版を使用しようとするユーザーは、そのバージョンを pip requirements.txt ファイルの中で参照することができます。以下はバージョン管理の例です。
1.0.1 # 1.0.1 final release 1.0.2a # 1.0.2 Alpha (for Alpha, after Dev releases) 1.0.2a.dev5 # 1.0.2 Alpha, Dev release #5 |
ソフトウェアが公開されていない限り、そのソフトウェアを見つけてインストールすることは通常はできません。ほとんどの場合、PyPI
にパッケージを公開する必要があります。.pypirc 構成ファイルをセットアップした後、setup.py に upload コマンドを渡すと、そのパッケージが PyPI に送信されます。通常はそれをソース・ディストリビューションのビルドと同時に行います。
python setup.py sdist upload |
独自の配布サーバーを使用している場合には、その配布サーバーのロケーションに対して認証を行うためのセクションを .pypirc ファイルに追加し、アップロードの際にそのセクション名を指定することで、そのセクションの情報を参照します。以下はその一例です。
python setup.py sdist upload -r mydist |
オープンソースの場合、独自の配布サーバーを使用する最大の理由は dev リリースの公開場所を提供するためです。PyPI は本来、安定版リリースのみで構成されているべきものだからです。例えば、PyPI に公開されている最新の安定版リリースをインストールするためには以下のようにします。
pip install MyPackage |
しかし後で dev リリースを追加すると、上記のコマンドによって最新リリースをインストールすることになり、それは dev リリースをインストールすることを意味します。通常は、必ずリリースのバージョンまで指定するのが望ましいですが、すべてのユーザーがそうするとは限りません。そのため、バージョン番号が指定されない場合には必ず最新の安定版リリースが返されるようにする必要があります。
標準的な方法で pip を実行する場合のために安定版リリースのみを公開する一方で、パッケージ化された dev
リリースをユーザーがインストールすることもできるようにする 1 つの方法は、独自の配布サーバーをホストする方法です。Pinax プロジェクト (
http://dist.pinaxproject.com) では、それをすべての dev リリースに対して行っています。(「参考文献」を参照。)
配布サーバーはサーバー上にあるファイルを HTTP (HyperText Transfer Protocol) で提供するための単なる索引にすぎません。索引を構成するファイルは以下のディレクトリー構造に従っていなければなりません。
/index-name/package-name/package-name-version.tar.gz |
必要な場合には、Web サーバーの Basic-Auth を構成することで配布サーバーをプライベートにすることもできます。ソース・ディストリビューションをアップロードする機能も追加する必要があるかもしれません。そのためには、アップロードの処理や、ファイル名の構文解析、そして上記の構造を満たすディレクトリー・パスの作成のためのコードが必要です。いくつものリポジトリーをホストする Pinax プロジェクトには、この構造が採用されています。
この記事は主にパッケージ化に焦点を絞りましたが、このセクションではパッケージを利用する場合に注目し、適切なパッケージ化とバージョン管理によってプロジェクトの利用者にどんなメリットがもたらされるのかを説明します。
pip は直接インストールすることもできるツールですが、私は virtualenv (「参考文献」を参照) の一部として pip を使用する方法を推奨します。virtualenv を使用すると
Python 環境をすっきりと維持できるため、Pthon に関連するあらゆるものに virtualenv
を使用するようお勧めします。仮想マシンによって複数のオペレーティング・システムを並列に実行できるのと同じように、virtualenv によって複数の Python 環境を並列に実行することができます。私は自分のシステムの Python
には何もインストールせず、新しいプロジェクトやユーティリティーを扱うごとに新しい virtualenv を作成するようにしています。
virtualenv をインストールしたところで、以下のように実行してみましょう。
$ mkvirtualenv —no-site-packages testing
$ pip install Pinax
$ pip freeze|grep Pinax
$ pip uninstall Pinax
$ pip install —extra-index-url=http://dist.pinaxproject.com/fresh-start/
Pinax==0.9a2.dev1017
$ pip freeze|grep Pinax
|
最初の pip install によって PyPI から Pinax
がダウンロードされてインストールされたことに注意してください。pip freeze により、現在の virtualenv にインストールされたパッケージのすべてのバージョンが表示されます。pip
uninstall はご想像どおり、virtualenv から Pinax を削除します。次に、開発版である Pinax バージョン 0.9a2.dev1017 を取得するために http://dist.pinaxproject.com にアクセスし、fresh-start リポジトリーからこの開発版をインストールします。
プロジェクトの利用者は、Web サイトへのアクセスや tarball のダウンロード、サイト内のパッケージへシンボリック・リンクするコードの作成などの作業は必要ありません (以前、私はこれらの作業を行っていましたが、それによって多くの問題が発生していました)。プロジェクトを提供する際に、適切にパッケージ化し、公開し、バージョン管理することで、利用者はこうした作業をまったくせずに済むのです。
結論は、パッケージ化の芸術と科学を学ぶために、少し時間をかける価値があるということです。パッケージをバージョン管理することによってインストールが容易になり、安定性が高まることで、より多くのユーザーが皆さんのプロジェクトを採用するようになるはずです。この記事で説明し、「参考文献」にも挙げたテンプレート setup.py
を使用することにより、皆さんのプロジェクトを素早く容易にパッケージ化できるはずです。適切なバージョン管理によってユーザーとコミュニケーションすることはユーザーに対する配慮であり、それによってユーザーはリリースごとの変更を容易に追跡できるようになります。そして、pip と virtualenv が広く採用されるようになるにつれ、(PyPI で公開する場合であれ独自の配布サーバーで公開する場合であれ) 公開されたパッケージを利用する人達の数も増えていきます。そのため、世界と共有したいプロジェクトは必ず公開するようにしてください。
この記事が、出発点として十分な情報を提供できたことを祈ります。「参考文献」には、さらに深く学ぶための資料を挙げてあります。質問がある場合には、Freenode のチャット・ルーム #pinax や #django-social などで遠慮なく私に連絡していただくか (ニックネームは “paltman” です)、あるいは Twitter (@paltman) で私をフォローしてください。
学ぶために
- PyPI について調べてください。
- setuptools 0.6c11 のサイトを訪れ、Python パッケージを容易にダウンロード、ビルド、インストール、アンインストールする方法を学んでください。
- PEP
0386 のサイトを訪れ、ディストリビューションをバージョン比較するモジュールに関して調べてください。
- Python
モジュールの配布方法に関して学んでください。
- developerWorks の Open Source
ゾーンにはオープンソース・ツールに関する情報やオープンソース技術の使い方に関する情報が豊富に用意されています。これまでに公開された Python 関連の他の記事もご覧ください。
- developerWorks podcasts でソフトウェア開発者のための興味深いインタビューや議論を聞いてください。
- Technical events and
webcasts で最新情報を入手してください。
- IBM
オープンソース開発者にとって関心のある、世界中で今後開催される会議や業界展示会、ウェブキャスト、その他のイベントについて調べてみてください。
- IBM とオープンソース技術、そして製品機能を調べ、学ぶために、無料の developerWorks On demand
demos をご覧ください。
製品や技術を入手するために
pipについて学び、pip をダウンロードしてください。virtualenvについて学び、virtualenv をダウンロードしてください。- この記事で使用したテンプレート setup.py を見つけてください。
- Django
の上に構築されたオープンソース・プラットフォーム、Pinax について調べてください。
- 皆さんの次期オープンソース開発プロジェクトを IBM ソフトウェアの試用版を使って革新してください。
議論するために
- developerWorks のブログから developerWorks のコミュニティーに参加してください。
