イマドキのPython in 2013

この投稿は QiitaのPython Advent Calendar 2013 の22日目の記事です。

はじめに

本記事は自分がPyPIに公開できるPythonモジュールを書くために行った調査結果をまとめたものです。が、私自身は未だかつて一度もPyPIにパッケージ*1を登録したことがないことを初めに断っておきます。

イマドキのツール群

  • 配布
    • distutils
    • setuptools (distribute)
  • 環境構築
    • easy_install
    • pip
    • virtualenv
    • pyenv, pythonz, pythonbrew
  • テスト
    • unittest2
    • pytest
    • tox
  • ドキュメント

以上、適当に列挙してみました。上から説明していきます。

配布

先に配布周りについて整理しておきます。環境構築はこの配布ツール周りの影響を強く受けているため、こちらを理解しておいたほうが後が楽だと思います。

Distutils

DistutilsPythonビルトインの配布ユーティリティです。これを使うことで、パッケージのインストールや配布が可能となります。基本的な使い方は、setup.py*2という名前のスクリプトに、distutils.core.setup関数を呼び出す処理を書くだけです。setup.pyを書いたら、

$ python setup.py sdist

でアーカイブ*3を作成出来たり*4

$ python setup.py install

でモジュールをインストールできたりします。

setuptools (distribute)

setuptoolsはDistutilsを拡張したライブラリです。pipa (Python Packaging Authority)によって開発されています。PyPIに登録されていることから分かるように、Pythonの数あるパッケージの1つに過ぎませんが、非常に広く使われており、半公式と言っても差し支えないかもしれません。Distutilsとの違いとしては、eggという、Javaのjar的なアーカイブを作成できる点が挙げられますが、ここでは詳細は割愛します(参考)。

ところで、見出しにdistributeというのを括弧つきで書いているのですが、これは何かというと、setuptoolsのフォークプロジェクトです。一時期setuptoolsが更新されなかったのがフォークの動機のようで、ネットで検索すると2010〜2012年ごろの記事で、setuptoolsはもう更新されていないからdistribute使おう、と紹介しているものが多数見受けられます。が、最近また事情が変わり、distributeがsetuptoolsにマージされることが決まりました。ということで、これからはsetuptoolsを使うのが正解となりそうです。

Where does the merge occur?

The merge is occurring between the heads of the default branch of Distribute and the setuptools-0.6 branch of Setuptools. The Setuptools SVN repo has been converted to a Mercurial repo hosted on Bitbucket. The work is still underway, so the exact changesets included may change, although the anticipated merge targets are Setuptools at 0.6c12 and Distribute at 0.6.35.

Setuptools/Distribute Merge FAQ — Setuptools documentation

さて、setuptoolsは、サードパーティのライブラリなので、当然のことながらPythonの素の環境には入っていません。これを鑑みてのことか、setuptoolsにはez_setup.pyというインストール用スクリプトが用意されています。また、ez_setup.pyを使うと、easy_install(後述)というパッケージ管理ツールも同時にインストールされます。

Download ez_setup.py and run it using the target Python version. The script will download the appropriate version and install it for you:

$ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | python
https://pypi.python.org/pypi/setuptools#installation-instructions

ちなみに、ネットを検索すると、 http://peak.telecommunity.com/dist/ez_setup.py なるURLのez_setup.pyを使ってインストールする記事がちらほら見受けられますが、こちらだとsetuptoolsのバージョンが古いので、PyPIに書いてある方法でインストールした方が良さそうです。

環境構築

easy_install

前述の通り、setuptoolsと一緒に入ってくるパッケージ管理ツールです。これを使うと、PyPIにあるパッケージを名前を指定するだけでインストールできたり、アップデートできたりします。が、もちろんeasy_installを使っても良いのですが、実際には後述のpipを使うことが多いです。

pip

pipは、easy_installより高性能なパッケージ管理ツールです。こちらもpypaにより開発されており、easy_installとの親和性は高いです。ドキュメントによれば、pipはeasy_installの完全な置換えというわけではなく、easy_installに出来て、pipに出来ないこともあるようです。

インストールはPyPIからインストールする(easy_installを使う)方法や、get-pip.pyを使う方法などがあります*5

$ easy_install pip
or
$ curl -fsSL https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python 

pipさえ入ってしまえばパッケージ管理に関して向かう所敵なしですね。

virtualenv

次にvirtualenvです。こちらもpypaにより開発されています。

virtualenvは、ライブラリなどが一切入っていないまっさらなPython環境を仮想的に作成するツールです。これを使うことで、Rubyのbundlerでvendor/bundleディレクトリでgemをアプリケーションローカルで管理してbundler execするとか、Node.jsでnpm installするとnode_modulesでモジュールが管理・利用されるとか、そういったことと同じことができるようなります。

インストールはpipで出来ます。

$ pip install virtualenv

使い方は、virtualenvコマンドで環境を作成し、sourceコマンドでbin/activateシェルスクリプトを実行するだけです。

$ virtualenv ~/.virtualenvs/hoge(どこでもOK)
$ source ~/.virtualenvs/hoge/bin/activate
(hoge)$ … (この中でpipなどを使うと、モジュールは仮想環境内にインストールされる)
(hoge)$ deactivate
$ ...

virtualenvの便利コマンドを提供してくれるvirtualenvwrapperというものもあるのですが、こちらは使ってないのでよく分かりません。

pyenv, pythonz, pythonbrew

pyenv, pythonz, pythonbrewはrbenv, plenvなどと同様なインタプリタ管理システムです。今のところ、複数バージョンのPythonインタプリタを管理する必要性が無く*6、まだこの手のものを導入していませんので、詳しいことは書けません。

とりあえず、pyenvが一番先進的なようなので、そちらを使うのが良さそうです。

テスト

あまり使いこなせてないので、ごく簡単に。

unittest2

unittest2はPython2.7と3.2以降に標準で搭載されているunittestモジュールのことです。〜2.6、〜3.1までのバージョンのunittestの高機能バージョンということでunittest2という名前がついたのだと思います。詳しくは以下を参照しましょう。

pytest

pytestはunittest2とは別のテストソリューションです。もっとも、unittest2のサポートもされているみたいです。

pytestをインストールするとpy.testというコマンドが提供され、ファイル名や関数名に接頭辞test_を付けると、自動で検出してテストを行ってくれたりします。また、エラーメッセージもunittest.main()よりも詳細に出してくれます。

他にも魅力があるようですが、使いこなせていないのでこれぐらいでご容赦を。

tox

複数のバージョンのPythonでテストを行いたい時に使えるツールのようです。

こちらも使ったことが無いため詳細が書けないのですが、githubにあるPythonのプロジェクト*7の殆どが使っているので、この用途ではスタンダードなツールだと思われます。

ドキュメント

Sphinx

元々Python用に作成されたようなのですが、今ではPython以外でもかなり使われているドキュメント生成ツールです。ただし、日本では海外ほど使われておらず*8、少し日本語の情報が乏しい感じがします。

ということで、簡単にチュートリアルを載せておきます。適宜以下を参照して下さい。

インストール

pipで出来ます。恐らくbrewなどでも出来ると思います。

$ pip install sphinx
事始め

sphinxをインストールすると自動で入る、sphinx-quickstartというコマンドでプロジェクトを作成します。

$ mkdir docs
$ cd docs
$ sphinx-quickstart
質問が出るので適当に回答。

大体Enter押しておけばOKです(参考)。

質問に回答し終えると、ひな形が自動生成されます。とりあえずこの状態でmakeが上手くいくか確認すると良いかもしれません。

$ make html
$ open _build/html/index.html
reStructuredText

SphinxではreStructuredText(.rst)という形式でドキュメントを書くのが一般的です。最初は少し取っ付きづらいのですが、これについては慣れるしか無いでしょう。

reStructuredTextにはmarkdown等と同様に、強調やリストなどをマークアップするための文法があり、その中にディレクティブという非常に汎用的な*9マークアップの仕組みがある、ということを抑えておくと良いかもしれません。

ディレクティブはSphinx側で定義されるので、何があるかはドキュメントを見る必要があります。

ディレクティブには、見出しの表示(toctree)、シンタックスハイライト(code)、ノート(note)や警告(caution)など色々有ります。ディレクティブを記述する際は、「行頭にドット2個、スペース、ディレクティブ名、コロン2個、スペース、オプション、改行、(インデントスペース3個)オプション、…、空行、(インデントスペース3個)コンテンツ」のように書くのが一般的です。

.. toctree::
   :maxdepth: 2

   modules

.. code:: python

    # コードの場合は4スペースインデントでも大丈夫そう
    # まぁトライアンドエラーで上手くやりましょう。
    print “Hello Sphinx!"

ソースコードに関する説明を記述したいときには、ドメインというのを利用してディレクティブを作成します。これは、ソースコードに記述するコメントとは全く別物です。ソースから自動生成したい時は次に説明する方法をとる必要があります。

ソースコードからドキュメントを生成

Pythonの場合*10、autodocという拡張機能を利用することにより、docstring形式で書いたソースコード中のコメントをドキュメントに組み込むことが出来ます。結構トラップが多いので、ここで個人的に引っかかった点をまとめておきます。

まず、conf.pyを書き換える必要があります。

...
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('..')) # ←モジュールが入っているディレクトリのパスを設定# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinx.ext.autodoc'] # ←autodocが必要
...

次に、autodocディレクティブを書くのですが、sphinx-apidocというコマンドを利用すると自動でひな形を生成することが出来ます。

$ cd docs/
$ sphinx-apidoc -f -o . mymodule

このsphinx-apidocですが、あくまでも自動生成なので、見た目がベストとは言えません。なので、最初に一回自動生成して、以降は適宜手直しするのがよいかもしれません。

利用例

試しにnacciモジュールというのを作成してみました。ディレクトリ構造は以下の通りです。

  • nacci/
    • .git/
    • nacci/
      • __init__.py
    • docs/
      • conf.py
      • ...
    • tests/
      • ...

イマドキの階層構造はこんな感じになるのだと思います。ただ、testsがパッケージ内に入っていることもあれば、docsの中にもう1階層あるものもあったりもするので、これといった決まりは無いようです。

conf.pyは前述の通り修正する必要があります。__init__.pyは以下になります。

"""Fibonacci Generators.

.. seealso::
   `Fibonacci number (Wikipedia) <http://en.wikipedia.org/wiki/Fibonacci_number>`_
"""

def fibo():
    """Generator of fibonacci numbers.
    """
    a, b = [0, 1]
    while True:
        yield a
        a = a + b
        a, b = b, a

def tribo():
    """Generator of tribonacci numbers.
    """
    a, b, c = [0, 0, 1]
    while True:
        yield a
        a = a + b + c
        a, b, c = b, c, a
        
def tetra():
    """Generator of tetranacci numbers.
    """
    a, b, c, d = [0, 0, 0, 1]
    while True:
        yield a
        a = a + b + c + d
        a, b, c, d = b, c, d, a

def nstep(n):
    """Generator of n-step fibonacci numbers.
    
    :param n: ``n``-step
    """
    nums = [0] * n
    nums[-1] = 1
    while True:
        t = sum(nums)
        yield nums.pop(0)
        nums.append(t)

index.rstを次のようにします。もっとファイルが沢山ある場合は、sphinx-apidocコマンドを使ったほうが良いでしょう。

.. nacci documentation master file, created by
   sphinx-quickstart on Sat Dec 21 22:31:10 2013.
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.

Welcome to nacci's documentation!
=================================

nacci module
------------

.. automodule:: nacci
    :members:
    :undoc-members:
    :show-inheritance:


Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

この状態で、make htmlすればHTMLドキュメントが出力されます。

f:id:s-shin:20131222011504p:plain

Read the Docs

最後に、Read the Docsというサイトを紹介しておきます。Read the Docsはドキュメントホスティングサービスで、Sphinxで生成したドキュメントを手軽に公開できるシステムです。試しにTornadoのドキュメントを生成してみましたが、GithubのURLを指定し、conf.pyの位置を指定するだけで、後は自動的によしなにやってくれるので大変便利です。

おわりに

この記事ではイマドキなツール類をバラバラに説明してきました。これらを使ってどうやってプロジェクトを作っていくかについては、やはり実際のプロジェクトを見るのが良いかと思います。GithubでPythonで検索してMost starsなプロジェクトをざっと眺めると非常に勉強になります。

真面目に書きすぎてしまいました。燃え尽きました。終わります。

*1:この文書では「パッケージ」「モジュール」「ライブラリ」等をほぼ同義で使います。厳密にはパッケージといえば __init__.py が直下に入っているディレクトリのことを指すのだと思います。モジュールとライブラリは同義かなぁ?

*2:慣例

*3:モジュールをtarballとかzipで固めたもの

*4:アーカイブするファイルはMANIFEST.inというので指定しますがここでは詳細は割愛

*5:コマンドは適当なので、間違ってたらスミマセン。

*6:と言うかMacに2.5, 2.6, 2.7, 3.2が既に入っているので

*7:Most starsの上位

*8:Python人口が少ないだけかも

*9:開発者側で自由に定義可能な

*10:Python以外の場合は分かりません。もしかしたら出来るかも? http://stackoverflow.com/q/11246637