2. setup スクリプトを書く

setup スクリプトは、Distutils を使ってモジュールをビルドし、配布し、インストールする際の全ての動作の中心になります。 setup スクリプトの主な目的は、モジュール配布物について Distutils に伝え、モジュール配布を操作するための様々なコマンドを正しく動作させることにあります。上の 簡単な例 の節で見てきたように、 setup スクリプトは主に setup() の呼び出しからなり、開発者が distuils に対して与えるほとんどの情報は setup() のキーワード引数として指定されます。

ここではもう少しだけ複雑な例: Distutils 自体の setup スクリプト、を示します。これについては、以降の二つの節でフォローします。 (Distutils が入っているのは Python 1.6 以降であり、 Python 1.5.2 ユーザが他のモジュール配布物をインストールできるようにするための独立したパッケージがあることを思い出してください。ここで示した、Distutils 自身の setup スクリプトは、Python 1.5.2 に Distutils パッケージをインストールする際に使います。)

#!/usr/bin/env python

from distutils.core import setup

setup(name='Distutils',
      version='1.0',
      description='Python Distribution Utilities',
      author='Greg Ward',
      author_email='gward@python.net',
      url='https://www.python.org/sigs/distutils-sig/',
      packages=['distutils', 'distutils.command'],
     )

上の例と、 簡単な例 で示したファイル一つからなる小さな配布物とは、違うところは二つしかありません: メタデータの追加と、モジュールではなくパッケージとして pure Python モジュール群を指定しているという点です。この点は重要です。というのも、 Distutils は 2 ダースものモジュールが (今のところ) 二つのパッケージに分かれて入っているからです; 各モジュールについていちいち明示的に記述したリストは、作成するのが面倒だし、維持するのも難しくなるでしょう。その他のメタデータについては、 追加のメタデータ を参照してください。

setup スクリプトに与えるパス名 (ファイルまたはディレクトリ) は、 Unix におけるファイル名規約、つまりスラッシュ ('/') 区切りで書かねばなりません。Distutils はこのプラットフォーム中立の表記を、実際にパス名として使う前に、現在のプラットフォームに適した表記に注意深く変換します。この機能のおかげで、setup スクリプトを異なるオペレーティングシステム間にわたって可搬性があるものにできます。言うまでもなく、これは Distutils の大きな目標の一つです。この精神に従って、このドキュメントでは全てのパス名をスラッシュ区切りにしています。

もちろん、この取り決めは Distutils に渡すパス名だけに適用されます。もし、例えば glob.glob()os.listdir() のような、標準の Python 関数を使ってファイル群を指定するのなら、パス区切り文字 (path separator) をハードコーディングせず、以下のように可搬性のあるコードを書くよう注意すべきです:

glob.glob(os.path.join('mydir', 'subdir', '*.html'))
os.listdir(os.path.join('mydir', 'subdir'))

2.1. パッケージを全て列挙する

packages オプションは、 packages リスト中で指定されている各々のパッケージについて、パッケージ内に見つかった全ての pure Python モジュールを処理 (ビルド、配布、インストール、等) するよう Distutils に指示します。このオプションを指定するためには、当然のことながら各パッケージ名はファイルシステム上のディレクトリ名と何らかの対応付けができなければなりません。デフォルトで使われる対応関係はきわめてはっきりしたものです。すなわち、パッケージ distutils が配布物ルートディレクトリからの相対パス distutils で表されるディレクトリ中にあるというものです。つまり、setup スクリプト中で packages = ['foo'] と指定したら、スクリプトの置かれたディレクトリからの相対パスで foo/__init__.py を探し出せると Distutils に確約したことになります。この約束を裏切ると Distutils は警告を出しますが、そのまま壊れたパッケージの処理を継続します。

ソースコードディレクトリの配置について違った規約を使っていても、まったく問題はありません: 単に package_dir オプションを指定して、 Distutils に自分の規約を教えればよいのです。例えば、全ての Python ソースコードを lib 下に置いて、 "ルートパッケージ" 内のモジュール (つまり、どのパッケージにも入っていないモジュール) を lib 内に入れ、 foo パッケージを lib/foo に入れる、といった具合にしたいのなら

package_dir = {'': 'lib'}

を setup スクリプト内に入れます。辞書内のキーはパッケージ名で、空のパッケージ名はルートパッケージを表します。キーに対応する値はルートパッケージからの相対ディレクトリ名です、この場合、 packages = ['foo'] を指定すれば、 lib/foo/__init__.py が存在すると Distutils に確約したことになります。

もう一つの規約のあり方は foo パッケージを lib に置き換え、 foo.bar パッケージが lib/bar にある、などとするものです。このような規約は、 setup スクリプトでは

package_dir = {'foo': 'lib'}

のように書きます。 package_dir 辞書に package: dir のようなエントリがあると、 package の下にある全てのパッケージに対してこの規則が暗黙のうちに適用され、その結果 foo.bar の場合が自動的に処理されます。この例では、 packages = ['foo', 'foo.bar'] は、 Distutils に lib/__init__.pylib/bar/__init__.py を探すように指示します。 (package_dir は再帰的に適用されますが、この場合 packages の下にある全てのパッケージを明示的に指定しなければならないことを心に留めておいてください: Distutils は __init__.py を持つディレクトリをソースツリーから再帰的にさがしたりは しません 。)

2.2. 個々のモジュールを列挙する

小さなモジュール配布物の場合、パッケージを列挙するよりも、全てのモジュールを列挙するほうがよいと思うかもしれません — 特に、単一のモジュールが "ルートパッケージ" にインストールされる (すなわち、パッケージは全くない) ような場合がそうです。この最も単純なケースは 簡単な例 で示しました; ここではもうちょっと入り組んだ例を示します:

py_modules = ['mod1', 'pkg.mod2']

ここでは二つのモジュールについて述べていて、一方は "ルート" パッケージに入り、他方は pkg パッケージに入ります。ここでも、デフォルトのパッケージ/ディレクトリのレイアウトは、二つのモジュールが mod1.pypkg/mod2.py にあり、 pkg/__init__.py が存在することを暗示しています。また、パッケージ/ディレクトリの対応関係は package_dir オプションでも上書きできます。

2.3. 拡張モジュールについて記述する

pure Python モジュールを書くより Python 拡張モジュールを書く方がちょっとだけ複雑なように、 Distutils での拡張モジュールに関する記述もちょっと複雑です。pure モジュールと違い、単にモジュールやパッケージを列挙して、Distutils が正しいファイルを見つけてくれると期待するだけでは十分ではありません; 拡張モジュールの名前、ソースコードファイル (群) 、そして何らかのコンパイル/リンクに関する必要事項 (include ディレクトリ、リンクすべきライブラリ、等) を指定しなければなりません。

それらは全て、もう 1 つの setup() のオプション引数、 ext_modules オプションを通じて行われます。 ext_modules は単なる Extension のリストで、それぞれがある 1 つの拡張モジュールを記述しています。配布物に、 foo という名前の foo.c に実装がある拡張モジュールが 1 つ含まれているとします。コンパイラ/リンカへのこれ以上の指示が無い場合は、拡張モジュールの記述は単純です:

Extension('foo', ['foo.c'])

Extension クラスは、 setup() によって、 distutils.core から import されます。従って、拡張モジュールが一つだけ入っていて、他には何も入っていないモジュール配布物を作成するための setup スクリプトは、以下のようになるでしょう:

from distutils.core import setup, Extension
setup(name='foo',
      version='1.0',
      ext_modules=[Extension('foo', ['foo.c'])],
      )

Extension クラス (実質的には、 Extension クラスの根底にある build_ext コマンドで実装されている、拡張モジュールをビルドする機構) は、Python 拡張モジュールをきわめて柔軟に記述できるようなサポートを提供しています。これについては後の節で説明します。

2.3.1. 拡張モジュールの名前とパッケージ

Extension コンストラクタの第 1 引数は、常に任意のパッケージ名を含む拡張モジュールの名前です。例えば、

Extension('foo', ['src/foo1.c', 'src/foo2.c'])

とすると、拡張モジュールをルートパッケージに置くことになります。一方

Extension('pkg.foo', ['src/foo1.c', 'src/foo2.c'])

は、同じ拡張モジュールを pkg パッケージの下に置くよう記述しています。ソースコードファイルと、作成されるオブジェクトコードはどちらの場合でも同じです; 作成された拡張モジュールがファイルシステム上のどこに置かれるか (すなわち Python の名前空間上のどこに置かれるか) が違うにすぎません。

同じパッケージ内に (または、同じ基底パッケージ下に) いくつもの拡張モジュールがある場合、 ext_package キーワード引数を setup() に指定します。例えば、

setup(...,
      ext_package='pkg',
      ext_modules=[Extension('foo', ['foo.c']),
                   Extension('subpkg.bar', ['bar.c'])],
     )

とすると、 foo.c をコンパイルして pkg.foo にし、 bar.c をコンパイルして pkg.subpkg.bar にします。

2.3.2. 拡張モジュールのソースファイル

Extension コンストラクタの第 2 引数は、ソースファイルのリストです。 Distutils は現在 C 、 C++ 、 Objective-C 拡張モジュールしかサポートしていないため、それらは通常は C/C++/Objective-C ソースファイルです。 (C++ ソースファイルと判別できるように適切な拡張子を使用するようにしてください: .cc.cpp が Unix と Windows のコンパイラの両方が認識できるようです。)

ただし、 SWIG インタフェース (.i) ファイルはリストに含められます; build_ext コマンドは、 SWIG で書かれた拡張パッケージをどう扱えばよいか心得ています: build_ext は、インタフェースファイルを SWIG にかけ、得られた C/C++ ファイルをコンパイルして拡張モジュールを生成します。

この警告にかかわらず、現在次のようにしてSWIGに対してオプションを渡すことができます:

setup(...,
      ext_modules=[Extension('_foo', ['foo.i'],
                             swig_opts=['-modern', '-I../include'])],
      py_modules=['foo'],
     )

もしくは、次のようにコマンドラインからオプションを渡すこともできます:

> python setup.py build_ext --swig-opts="-modern -I../include"

プラットフォームによっては、コンパイラで処理され、拡張モジュールに取り込まれるような非ソースコードファイルを含められます。非ソースコードファイルとは、現状では Visual C++向けの Windows メッセージテキスト (.mc) ファイルや、リソース定義 (.rc) ファイルを指します。これらのファイルはバイナリリソース (.res) ファイルにコンパイルされ、実行ファイルにリンクされます。

2.3.3. プリプロセッサオプション

検索するインクルードディレクトリやプリプロセッサマクロの define/undefine を指定する必要がある場合、 Extension の 3 つのオプション引数が役に立ちます: include_dirsdefine_macrosundef_macros です。

例えば、拡張モジュールが配布物ルート下の include ディレクトリにあるヘッダファイルを必要とするときには、 include_dirs オプションを使います:

Extension('foo', ['foo.c'], include_dirs=['include'])

ここには絶対パスも指定できます; 例えば、自分の拡張モジュールが、 /usr の下にX11R6 をインストールした Unix システムだけでビルドされると知っていれば、このように書けます

Extension('foo', ['foo.c'], include_dirs=['/usr/include/X11'])

自分のコードを配布する際には、このような可搬性のない使い方は避けるべきです: おそらく、C のコードを次のように書いたほうがましでしょう

#include <X11/Xlib.h>

他の Python 拡張モジュール由来のヘッダを include する必要があるなら、 Distutils の install_header コマンドが一貫した方法でヘッダファイルをインストールするという事実を活用できます。例えば、 Numerical Python のヘッダファイルは、 (標準的な Unix がインストールされた環境では) /usr/local/include/python1.5/Numerical にインストールされます。 (実際の場所は、プラットフォームやどの Python をインストールしたかで異なります。) Python の include ディレクトリ — 今の例では /usr/local/include/python1.5 — は、 Python 拡張モジュールをビルドする際に常にヘッダファイル検索パスに取り込まれるので、 C コードを書く上でもっともよいアプローチは、以下のようなものとなります

#include <Numerical/arrayobject.h>

Numerical インクルードディレクトリ自体をヘッダ検索パスに置きたいのなら、このディレクトリを Distutils の distutils.sysconfig モジュールを使って見つけさせられます:

from distutils.sysconfig import get_python_inc
incdir = os.path.join(get_python_inc(plat_specific=1), 'Numerical')
setup(...,
      Extension(..., include_dirs=[incdir]),
      )

この書き方も可搬性はあります — プラットフォームに関わらず、どんな Python がインストールされていても動作します — が、単に実践的な書き方で C コードを書く方が簡単でしょう。

define_macros および undef_macros オプションを使って、プリプロセッサマクロを定義 (define) したり、定義解除 (undefine) したりもできます。 define_macros はタプル (name, value) からなるリストを引数にとります。 name は定義したいマクロの名前 (文字列) で、 value はその値です: value は文字列か None になります。(マクロ FOONone にすると、C ソースコード内で #define FOO と書いたのと同じになります: こう書くと、ほとんどのコンパイラは FOO を文字列 1 に設定します。) undef_macros には、定義解除したいマクロ名からなるリストを指定します。

例えば:

Extension(...,
          define_macros=[('NDEBUG', '1'),
                         ('HAVE_STRFTIME', None)],
          undef_macros=['HAVE_FOO', 'HAVE_BAR'])

は、全ての C ソースコードファイルの先頭に、以下のマクロがあるのと同じになります:

#define NDEBUG 1
#define HAVE_STRFTIME
#undef HAVE_FOO
#undef HAVE_BAR

2.3.4. ライブラリオプション

拡張モジュールをビルドする際にリンクするライブラリや、ライブラリを検索するディレクトリも指定できます。 libraries はリンクするライブラリのリストで、 library_dirs はリンク時にライブラリを検索するディレクトリのリストです。また、 runtime_library_dirs は、実行時に共有ライブラリ (動的にロードされるライブラリ) を検索するディレクトリのリストです。

例えば、ビルド対象システムの標準ライブラリ検索パスにあることが分かっているライブラリをリンクする時には、以下のようにします

Extension(...,
          libraries=['gdbm', 'readline'])

非標準のパス上にあるライブラリをリンクしたいなら、その場所を library_dirs に入れておかなければなりません:

Extension(...,
          library_dirs=['/usr/X11R6/lib'],
          libraries=['X11', 'Xt'])

(繰り返しになりますが、この手の可搬性のない書き方は、コードを配布するのが目的なら避けるべきです。)

2.3.5. その他のオプション

他にもいくつかオプションがあり、特殊な状況を扱うために使います。

optional オプションはブール型で、真の場合は拡張モジュールのビルドに失敗したときにビルドプロセス自体を停止せず、単にその拡張モジュールのインストールをしません。

extra_objects オプションには、リンカに渡すオブジェクトファイルのリストを指定します。ファイル名には拡張子をつけてはならず、コンパイラで使われているデフォルトの拡張子が使われます。

extra_compile_args および extra_link_args には、それぞれコンパイラとリンカに渡す追加のコマンドライン引数を指定します。

export_symbols は Windows でのみ意味があります。このオプションには、公開 (export) する (関数や変数の) シンボルのリストを入れられます。コンパイルして拡張モジュールをビルドする際には、このオプションは不要です: Distutils は公開するシンボルを自動的に initmodule に渡すからです。

depends オプションは、拡張モジュールが依存している(例: ヘッダーファイルなどの) ファイルのリストです。このファイルのいずれかが前回のビルドから変更された時、ビルドコマンドはこのソースファイルをコンパイルしてリビルドします。

2.4. パッケージと配布物の関係

配布物はパッケージと3種類の方法で関係します:

  1. パッケージかモジュールを要求する。
  2. パッケージかモジュールを提供する。
  3. パッケージかモジュールを廃止する。

これらの関係は、 distutils.core.setup() 関数のキーワード引数を利用して指定することができます。

他のPythonモジュールやパッケージに対する依存は、 setup()requires キーワード引数で指定できます。引数の値は文字列のリストでなければなりません。各文字列は、必要とするパッケージと、オプションとしてパッケージのバージョンを指定します。

あるモジュールかパッケージの任意のバージョンが必要な場合、指定する文字列はモジュール名かパッケージ名になります。例えば、 'mymodule''xml.parsers.expat' を含みます。

特定のバージョンが必要な場合、修飾子(qualifier)の列を加えることができます。各修飾子は、比較演算子とバージョン番号からなります。利用できる比較演算子は:

<    >    ==
<=   >=   !=

これらの修飾子はカンマ(空白文字を入れても良いです)で区切って複数並べることができます。その場合、全ての修飾子が適合する必要があります; 評価する時に論理ANDでつなげられます。

いくつかの例を見てみましょう:

require式 説明
==1.0 version 1.0 のみが適合します
>1.0, !=1.5.1, <2.0 1.5.1 を除いて、 1.0 より後ろで 2.0 より前の全てのバージョンに適合します。

これで、依存を指定することができました。同じように、この配布物が他の配布物に必要とされる何を提供するのかを指定する必要があります。これは、 setup()provides キーワード引数によって指定できます。この引数の値は文字列のリストで、各要素はPythonモジュールかパッケージの名前です。バージョンを指定することもできます。もしバージョンが指定されなかった場合、配布物のバージョン番号が利用されます。

いくつかの例です:

provide 式 説明
mypkg mypkg を提供します。バージョンは配布物のものを使います。
mypkg (1.1) mypkg version 1.1 を提供します。配布物のバージョン番号は気にしません

パッケージは obsoletes キーワードを利用することで、他のパッケージを廃止することを宣言することもできます。この値は requires キーワードと似ています: モジュールやパッケージを指定する文字列のリストです。各文字列は、モジュールかパッケージの名前と、オプションとして一つ以上のバージョン指定から構成されています。バージョン指定は、モジュールやパッケージの名前のうしろに、丸括弧(parentheses)でかこわれています。

指定されたバージョンは、その配布物によって廃止されるバージョンを示しています。バージョン指定が存在しない場合は、指定された名前のモジュールまたはパッケージの全てが廃止されたと解釈されます。

2.5. スクリプトをインストールする

ここまでは、スクリプトから import され、それ自体では実行されないような pure Python モジュールおよび非 pure Python モジュールについて扱ってきました。

スクリプトとは、Python ソースコードを含むファイルで、コマンドラインから実行できるよう作られているものです。スクリプトは Distutils に複雑なことを一切させません。唯一の気の利いた機能は、スクリプトの最初の行が #! で始まっていて、 "python" という単語が入っていた場合、Distutils は最初の行を現在使っているインタプリタを参照するよう置き換えます。デフォルトでは現在使っているインタプリタと置換しますが、オプション --executable (または -e) を指定することで、明示的にインタプリタのパスを指定して上書きすることができます。

scripts オプションには、単に上で述べた方法で取り扱うべきファイルのリストを指定するだけです。PyXML の setup スクリプトを例に示します:

setup(...,
      scripts=['scripts/xmlproc_parse', 'scripts/xmlproc_val']
      )

バージョン 3.1 で変更: テンプレートが提供されない時、全てのスクリプトが MANIFEST ファイルに追加されるようになりました。 配布するファイルを指定する を参照してください

2.6. パッケージデータをインストールする

しばしばパッケージに追加のファイルをインストールする必要があります。このファイルは、パッケージの実装に強く関連したデータや、そのパッケージを使うプログラマーが必要とするドキュメントなどです。これらのファイルを パッケージデータ と呼びます。

パッケージデータは関数 setup() にキーワード引数 package_data を与えることで追加できます。この値はパッケージ名から、パッケージへコピーされる相対パス名リストへのマップである必要があります。それぞれのパスは対応するパッケージが含まれるディレクトリ(もし適切なら package_dir のマッピングが利用されます)からの相対パスとして扱われます。つまり、ファイルはソースディレクトリ中にパッケージの一部として存在すると仮定されています。この値にはグロブパターンを含むことができます。

パス名にはディレクトリ部分を含むことができます。必要なディレクトリはインストール時に作成されます。

たとえば、パッケージがいくつかのデータファイルを含むサブディレクトリを含んでいる場合、ソースツリーでは以下のように配置できます:

setup.py
src/
    mypkg/
        __init__.py
        module.py
        data/
            tables.dat
            spoons.dat
            forks.dat

対応する setup() 呼び出しは以下のようになります:

setup(...,
      packages=['mypkg'],
      package_dir={'mypkg': 'src/mypkg'},
      package_data={'mypkg': ['data/*.dat']},
      )

バージョン 3.1 で変更: テンプレートが提供されない時、全ての package_data にマッチするファイルが MANIFEST ファイルに追加されるようになりました。 配布するファイルを指定する を参照してください

2.7. 追加のファイルをインストールする

data_files オプションを使うと、モジュール配布物で必要な追加のファイル: 設定ファイル、メッセージカタログ、データファイル、その他これまで述べてきたカテゴリに収まらない全てのファイルを指定できます。

data_files には、(directory, files) のペアを以下のように指定します:

setup(...,
      data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']),
                  ('config', ['cfg/data.cfg']),
                  ('/etc/init.d', ['init-script'])]
     )

データファイルのインストール先ディレクトリ名は指定できますが、データファイル自体の名前の変更はできないので注意してください。

各々の (directory, files) ペアには、インストール先のディレクトリ名と、そのディレクトリにインストールしたいファイルを指定します。 directory が相対パスの場合、インストールプレフィクス (installation prefix、 pure Python パッケージなら sys.prefix 、拡張モジュールの入ったパッケージなら sys.exec_prefix) からの相対パスと解釈されます。 files 内の各ファイル名は、パッケージソースコード配布物の最上階層の、 setup.py のあるディレクトリからの相対パスと解釈されます。 files に書かれたディレクトリ情報は、ファイルを最終的にどこにインストールするかを決めるときには使われません; ファイルの名前だけが使われます。

data_files オプションは、ターゲットディレクトリを指定せずに、単にファイルの列を指定できます。しかし、このやり方は推奨されておらず、指定すると install コマンドが警告を出力します。ターゲットディレクトリにデータファイルを直接インストールしたいなら、ディレクトリ名として空文字列を指定してください。

バージョン 3.1 で変更: テンプレートが提供されない時、全ての data_files にマッチするファイルが MANIFEST ファイルに追加されるようになりました。 配布するファイルを指定する を参照してください

2.8. 追加のメタデータ

setup スクリプトには、名前やバージョンにとどまらず、その他のメタデータを含められます。以下のような情報を含められます:

メタデータ 説明 注釈
name パッケージ名 短い文字列 (1)
version リリースのバージョン 短い文字列 (1)(2)
author パッケージ作者名 短い文字列 (3)
author_email パッケージ作者の電子メールアドレス 電子メールアドレス (3)
maintainer パッケージメンテナンス担当者の名前 短い文字列 (3)
maintainer_email パッケージメンテナンス担当者の電子メールアドレス 電子メールアドレス (3)
url パッケージのホームページ URL (1)
description パッケージについての簡潔な概要説明 短い文字列  
long_description パッケージについての詳細な説明 長い文字列 (5)
download_url パッケージをダウンロードできる場所 URL (4)
classifiers 分類語のリスト 文字列からなるリスト (4)
platforms プラットフォームのリスト 文字列からなるリスト  
license パッケージのライセンス 短い文字列 (6)

注釈:

  1. 必須のフィールドです。
  2. バージョン番号は major.minor[.patch[.sub]] の形式をとるよう奨めます。
  3. 作者かメンテナのどちらかは必ず区別してください。メンテナが与えられると、distutils は PKG-INFO に作者としてリストします。
  4. These fields should not be used if your package is to be compatible with Python versions prior to 2.2.3 or 2.3. The list is available from the PyPI website.
  5. パッケージを PyPI に 登録 する際、PyPI は long_description フィールドの値を使って パッケージのホームページをビルド します。
  6. license フィールドは、ライセンスが "License" Trove 分類から選ばれたのではない場合にパッケージをカバーするライセンスを示すテキストです。 Classifier フィールドを参照してください。お気づきの通り、廃止された licence というオプションがあり、未だに license のエイリアスとして働いています。
「短い文字列」
200 文字以内の一行のテキスト。
「長い文字列」
複数行からなり、ReStructuredText 形式で書かれたプレーンテキスト (http://docutils.sourceforge.net/ を参照してください)。
「文字列のリスト」
下記を参照してください。

バージョン情報のコード化は、それ自体が一つのアートです。 Python のパッケージは一般的に、 major.minor[.patch][sub] というバージョン表記に従います。メジャー (major) 番号は最初は 0 で、これはソフトウェアが実験的リリースにあることを示します。メジャー番号は、パッケージが主要な開発目標を達成したとき、それを示すために加算されてゆきます。マイナー (minor) 番号は、パッケージに重要な新機能が追加されたときに加算されてゆきます。パッチ (patch) 番号は、バグフィクス版のリリースが作成されたときに加算されます。末尾にバージョン情報が追加され、サブリリースを示すこともあります。これは "a1,a2,…,aN" (アルファリリースの場合で、機能や API が変更されているとき)、 "b1,b2,…,bN" (ベータリリースの場合で、バグフィクスのみのとき) 、そして "pr1,pr2,…,prN" (プレリリースの最終段階で、リリーステストのとき) になります。以下に例を示します:

0.1.0
パッケージの最初の実験的なリリース
1.0.1a2
1.0 の最初のパッチバージョンに対する、2 回目のアルファリリース

classifiers は、Python のリスト型で指定します:

setup(...,
      classifiers=[
          'Development Status :: 4 - Beta',
          'Environment :: Console',
          'Environment :: Web Environment',
          'Intended Audience :: End Users/Desktop',
          'Intended Audience :: Developers',
          'Intended Audience :: System Administrators',
          'License :: OSI Approved :: Python Software Foundation License',
          'Operating System :: MacOS :: MacOS X',
          'Operating System :: Microsoft :: Windows',
          'Operating System :: POSIX',
          'Programming Language :: Python',
          'Topic :: Communications :: Email',
          'Topic :: Office/Business',
          'Topic :: Software Development :: Bug Tracking',
          ],
      )

2.9. setup スクリプトをデバッグする

setup スクリプトのどこかがまずいと、開発者の思い通りに動作してくれません。

Distutils は setup 実行時の全ての例外を捉えて、簡単なエラーメッセージを出力してからスクリプトを終了します。このような仕様にしているのは、 Python にあまり詳しくない管理者がパッケージをインストールする際に混乱しなくてすむようにするためです。もし Distutils のはらわた深くからトレースバックした長大なメッセージを見たら、管理者はきっと Python のインストール自体がおかしくなっているのだと勘違いして、トレースバックを最後まで読み進んで実はファイルパーミッションの問題だったと気づいたりはしないでしょう。

しかし逆に、この仕様は開発者にとってはうまくいかない理由を見つける役には立ちません。そこで、 DISTUTILS_DEBUG 環境変数を空文字以外の何らかの値に設定しておけば、 Distutils が何を実行しているか詳しい情報を出力し、例外が発生した場合には完全なトレースバックをダンプし、(C コンパイラのような) 外部プログラムが失敗した時はコマンドライン全体を表示するようにできます。