はじめに
こんにちは、Python界の情弱です。情弱ながらPyCon JP 2012で1セッション持たせてもらえることになりました。予め資料を公開しておきますので、当日は色々と質問・意見して頂ければと思います。
各トピックは各トピックでの総論になっていますので、細かい部分は本文最後の参照にあるリンクを見るとより理解が深まります。
「なおここに書いてある内容は所属する団体とは関係のない、私個人の見解ですので、予めご了承下さい。」テンプレ終わり。
イベント | PyCon JP 2012 |
発表日時 | 2012-09-16 11:00-11:45 |
作者 | @ymotongpoo |
URL | http://2012.pycon.jp/program/sessions.html#session-16-1100-room357-ja |
スライド
(追記: 2012/09/16 23:50:00)
発表の24:00頃のpy.testに関する記述で「プラグインが書けない」という話は間違っていました。(詳しくは本文参照)
アジェンダ
- 自己紹介
- 概要
- ローカル開発環境
- コード編集
- Pythonの管理
- パッケージの管理
- ワークスペースの管理
- テストの管理
- 統合環境
- 継続テストの管理
- ドキュメントの管理
自己紹介
- id:ymotongpoo
- Google Inc., YouTube Technical Account Manager
- ここ1年は主にライブ配信のサポートなどを担当
- Pythonはツール作成などに使用
- 個人的には翻訳プロジェクトに従事
- Jinja2
- Tornado
概要
Pythonでサービスや製品開発をする際の土台作りについての考察をご紹介し、これからPythonでの開発を本格的に行う人の指針、あるいは他言語での開発に慣れた人がPythonでの開発を行う際のジャンプスタートとなることを目標としてお話します。
システム的に解決できる部分しか触れていないので、コーディング規約、レビュー制度などの運用的な話はしません。「PythonでWebアプリケーションを作るためのベストプラクティスがどうのこうの」という話もしません。
なお、発表時点ではPythonは3.3.0 rc1が最新版となっておりますが、本発表では特に断りのない限りPython 2系、特に2系の最新安定版であるPython2.7.3を基準にご紹介致します。
コード編集
好きなエディタ使って編集すればいいと思いますが、PythonではPEP8や、言語仕様としてブロックをインデントにて表現するため、エディタの支援を使わないと余計な苦労をするかもしれません。
Pythonの管理
まず開発の基準にするPythonをどう管理するかについて。OSによって管理方法が変わると思います。今回は一番一般的なPython実装であるCPythonについての説明をしますので、IronPython、PyPy、Jythonといった異なる実装に関しての環境設定については触れません。
CPythonの場合、そのインストール方法は大きく分けると
- ビルド済みバイナリ
- 自前ビルド
の2点です。
それぞれ長所短所があり、状況に応じてお好きな方法を選択されればいいかと思います。手軽さで言えばビルド済みバイナリですし、他システムとの連携や細かい設定を考えると自前ビルドでしょう。ビルド済みバイナリを用いる場合にはインストール先を指定できるか否かにも注意したいところです。
Windows
Windowsではソースからビルドするためには、Microsoft Visual C++が必要となります。通常はMSIパッケージを使ってインストールします。
- MSIパッケージ
MSIパッケージを用いる場合にはインストール先を指定できるため、複数バージョンをインストールする際にはインストール先を統一しておいたほうが良いと思います。
Mac OS X
Mac OS Xの場合OSに紐付いたハードウェアが限定されるという特殊な事情があります。homebrew, MacPortsの場合は各パッケージシステムのインストールルート以下の特定の場所に、dmgでは /Library/Frameworks/Python.framework にインストールされます。makeをする場合はXcodeにあるgccが必要になります。
- homebrew, MacPorts
- dmg
- make
pythonz (pythonbrew)
pythonzはPython専用のインストールマネージャです。
インストールマネージャと言っても、ビルド済みバイナリをダウンロードしてくるわけではなく、
1. tarballのダウンロード&展開
2. make
を自動で行うためのショートカットツールです。
元々はpythonbrewというツールをforkしたものでしたが、pythonzの方が機能はシンプルです。
ただしpythonbrew系ツールに関しては個人的にはおすすめはしません。
詳細は参考にある私見をご参照頂ければと思いますが、簡潔にまとめると次のとおりです。
- Pythonのインストール自体頻度は高くない
- 余計なエントリポイントを増やす必然性を感じない
- ビルド自体は難しくない
パッケージの管理
- setup.py (distutils, setuptools, distribute)
- easy_install (setuptools, distribute, distutils2)
- pip
setup.py
setup.pyはPythonモジュールを配布する際に必ず必要になるスクリプトファイルで、ファイル内にはモジュールのメタデータを含んだsetup関数が記載してあります。setup.pyの詳細は公式ドキュメントにゆずるとして、setup.pyの現状についてご紹介します。
setup関数自体はPython標準ライブラリのdistutils内で定義されていますが、依存ライブラリの解消や、エントリポイントなどの重要な機能がないため、setuptoolsがdistutilsの拡張として開発され、さらにその拡張としてdistributeが開発されています。
distutils -> setuptools -> distribute
歴史的な経緯はスライドを参照して頂ければと思いますが、とりあえずsetup.py使うときはdistributeを使いましょう。
easy_install
easy_installコマンドでややこしいのは、これ自体はsetuptoolsモジュールを叩くためのスクリプトであって、setuptoolsモジュールが複数のパッケージで実装されているということです。歴史的な経緯はスライドにあるとおりですが、setuptoolsよりもdistributeの方が後発で、開発も活発であり、多機能です。そしてそのdistributeの機能を取り込んだPython3.3以降の標準機能をバックポートしたものがdistutils2です。
発表時現在で現状有姿でPython3に対応しているのはdistributeのみであり、distributeが現時点でデファクトスタンダートとなっています。distributeで使えるeasy_installのオプションは次の通り。
--upgrade,-U | 強制アップグレード |
--always-unzip,-Z | zipは展開してインストール |
--multi-version,-m | 複数バージョンのインストールもしくはアンインストール |
他のオプションは easy_install --help で確認してください。
pip
パッケージ管理ツールとして、リリース当初easy_installにはなかったパッケージのアンインストール機能を始め、多くの機能があるツールです。
install | パッケージをインストール |
uninstall | パッケージをアンインストール |
bundle | pybundleを作成する(複数のパッケージを含むアーカイブを作る) |
freeze | 現在インストールされているパッケージを標準出力に表示 |
search | PyPIを検索 |
zip | 個々のパッケージをzipする |
unzip | 個々のパッケージをunzipする |
pipの場合、requirements.txtと呼ばれるファイルにsetup.pyのinstall_requestsと似た形式でパッケージを指定しておくと、次のようにまとめてパッケージのインストールができます。
$ cat requirements.txt MyApp Framework==0.9.4 Library>=0.2 $ pip install -r requirements.txt
pipは便利なのですが、easy_installとの互換性がないので、使うのであればどちらか一方にしたほうがいいでしょう。またpipはeggを扱えないなどの制限があるため、例えばIPythonのようなモジュールはインストールできないことに注意しましょう。
ワークスペースの管理
Pythonでは、開発しようとする製品に応じて、利用するPythonやライブラリのバージョンが異なることが往々にしてあります。
OSのすぐ上にあるPython環境でこれらの切り分けを行うことは現状では難しいため、3rd partyツールを利用して各プロジェクト用のワークスペースを作成/管理します。
- virtualenv (+virtualenvwrapper)
- zc.buildout
- venv (pyvenv from Python3.3)
virtualenv (+virtualenvwrapper)
virtualenvはPython仮想環境の管理ツールです。ここでいう仮想環境というのは、システムインストールされたPython本体から独立した、site-packagesを構築できるという意味です。
- 仮想環境の作成
virtualenvパッケージをインストールしたら、 virtualenv コマンドで仮想環境を作成します。ここでは spam という環境を作成します。
$ virtualenv spam
virtualenvではデフォルトではpipが標準のパッケージ管理ツールとして選択され、仮想環境にインストールされるわけですが、distributeのeasy_installを利用することもできます。その場合は次のように仮想環境を作成します。
$ virtualenv --distribute spam
distributeをデフォルトにする場合は環境変数 VIRTUALENV_DISTRIBUTE を true にしておきましょう。
$ export VIRTUALENV_DISTRIBUTE=true $ virtualenv egg
- 仮想環境の利用
仮想環境 spam を利用するには作成した仮想環境の activate スクリプトを実行します。
$ source spam/bin/activate (spam) $ easy_install -UZ bucho (spam) $ deactivate $
PS1に仮想環境名が表示されたら仮想環境がアクティブになっています。このときPATHの先頭に spam/bin が追加されているはずです。deactivate を実行すると環境変数が元に戻ります。
- virtualenvwrapper
virtualenvではワークスペースの管理や仮想環境の切り替えなどを手動で行う必要がありましたが、それらを使いやすくvirtualenvのラップしてくれたのがvirtualenvwrapperです。
インストール方法等は公式ドキュメントやブログエントリ等に任せるとして、仮想環境の作成や切り替えなどが非常に簡単になります。
$ mkvirtualenv spam (spam) $ mkvirtualenv egg (egg) $ workon spam egg (egg) $ workon spam (spam) $ deactivate $ rmvirtualenv egg spam $ workon spam (spam) $
zc.buildout
昨日のセッションで北崎さんが説明されていたので資料等はそちらもご参照ください。zc.buildout(以下、buildout)はPython製のビルドツールで、本来であればワークスペースの管理用のツールではありません。しかしながら、十分ワークスペース管理に便利に利用できるため、ここでご紹介します。なおbuildoutは2.0は現状buggyなので1.6を使うことをおすすめします。
buildoutを利用する方法は次の2通りあります。
- packageとしてzc.buildoutをインストールする
- bootstrap.py単体を取得する
- buildout初期化
まずbuildoutで環境を作成する場合は、専用のディレクトリを作成します。
1.で取得した場合は次の通り。
$ easy_install zc.buildout $ buildout init
2.で取得した場合は次の通り。
$ curl "https://raw.github.com/buildout/buildout/master/bootstrap/bootstrap.py -o /tmp/bootstrap.py $ python /tmp/boostrap.py init --distribute
- buildout.cfg設定
この時点でディレクトリは次のようになっています。
. ├── bin ├── buildout.cfg ├── develop-eggs ├── eggs └── parts
buildoutはデフォルトでターゲットディレクトリ内のbuildout.cfgというini形式ファイルを設定ファイルとして認識します。ここにビルドツールとして機能させるための設定を書くわけですが、今回は独立したsite-packagesを作るために利用します。
[buildout] parts = dev [dev] recipe = zc.recipe.egg eggs = sphinx sphinxcontrib-blockdiag sphinxcontrib-networkdiag PIL interpreter = py
- buildoutの実行
buildout.cfgの作成が完了したらbuildoutで環境を構築する。先ほどbootstrapした際に作成されたbinディレクトリに必要なコマンドが入っていますので、そちらから実行します。
$ bin/buildout ... zip_safe flag not set; analyzing archive contents... Got funcparserlib 0.3.5.
pyvenv (venv module)
pyvenvはvirtualenvに刺激を受けてPEP 405として提案された標準コマンドです。Python3.3より導入された機能ですので現時点ではまだ実用では使われないと思いますが、今後は上記のような3rd partyツールではなく、標準で使われる可能性も高いので、一応ご紹介しておきます。
- 仮想環境の作成
仮想環境の作成は非常に簡単です。
$ pyvenv /path/to/workspace
virtualenvによく似ていますね。
- 仮想環境の利用
作成した仮想環境のディレクトリに行き bin/ ディレクトリにある activate スクリプトを実行するだけ。
$ cd /path/to/workspace $ source bin/acivate (workspace) $
仮想環境内のパッケージの管理に関しては pip や easy_install をインストールする必要があります。
テストの管理
unittest, doctest
unittestとdoctestはPythonの標準ライブラリとして提供されるテストツールです。後述のnoseやpy.testほどの機能はありませんが、簡単なテストを書くだけなら十分に利用できます。
unittestでは名前の通りユニットテストを行うのに必要な基本的なツールは揃っていて、setup(), teardown()なども当然利用できます。
doctestは更に便利で、コード中にdocstringとして書いたものがそのままテストになります。簡単なスクリプトなどでわざわざ別にテスト用ファイルを作成するのが面倒なときには、ドキュメントついでにテストを書いておくと非常に便利です::
def square(n): """ square given number n >>> square(2) 4 >>> square(-5) 25 >>> square('one') Traceback (most recent call last): ... TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int' """ return pow(n, 2) if __name__ == "__main__": import doctest doctest.testmod()
nose vs py.test
noseとpy.testはどちらも似た思想で作られているので、どちらでもいいかなと思っていますが、個人的にはpy.testを推奨します。その理由は次のとおり。
- xUnit形式の出力がプラグインなしで可能(→Jenkinsとの連携が楽)
- 後述のtoxが依存しているため余計にインストールする必要がない
- テストデータとロジックを分けて書けるためすっきり書ける
あくまで個人的な印象です。noseのほうが先発だったこともあり、ユーザも多く多くの3rd partyプラグインやドキュメントが出ていて既存資産も多い方がたくさんいると思います。また、プラグインの機能はnoseにしかないので、特定の製品を長い期間メンテしていく上ではnoseの方が良いかも知れません。また情報も多いです。一方で後発のpy.testは必要な機能をデフォルトで実装していたため、単体で非常に利用しやすいテストランナーになっていると思います。
(修正: 2012/09/16 23:50:00)
コメントでid:Surgoより指摘を頂いて、py.testでもプラグインの実装ができることを知りました。いつの間にか出来るようになっていた!
こうなると今日話していた内容で考えるとnoseかpy.testの選択は既存資産が有るか否か、という点に落ち着きますね!
複数バージョンテスト
ライブラリの作成などに於いては、複数のバージョンに対応するために、複数のバージョンでのテストを行う必要があります。
- tox
- zc.buildout(一応紹介)
tox
toxは設定ファイルにしたがってテスト環境ごとにvirtualenvを使って仮想環境を自動作成し、さらに作成した仮想環境でテストランナーを走らせて、各テスト結果をまとめてレポートしてくれるという大変優れたツールです。さらに設定ファイルの書き方もそれほど難しくないのが素晴らしい。
toxの設定ファイルである tox.ini は次のように書けます。
[tox] envlist = py27, py32 [testenv] deps = pytest requests commands = py.test \ --junitxml=junit-{envname}.xml \ test
これで、py27, py32という仮想環境を作成し、xUnit形式のテスト結果を返してくれます。py.testを使っていますが、toxとpy.testは開発プロジェクトが同じで、py.testはtoxに同梱されています。そのため連携も非常に良く、これもpy.testをおすすめする理由の1つです。
zc.buildout
先ほどワークスペースの管理でも利用しましたが、テストランナーとしてもbuildoutが利用できます。 使うrecipeは次のどれか。
- zc.recipe.testrunner (通常のテスト)
- pbp.recipe.noserunner (noseを使う場合)
- z3c.recipe.scripts
- collective.recipe.template
継続テストの管理
継続テストでは、継続的インテグレーション(CI)ツールを利用します。
- Jenkins (+plugin)
- Travis CI
- Buildbot(紹介だけ)
Jenkins
Jenkinsは言わずと知れたJava製の継続的インテグレーションシステムです。単純に動作させるだけであればインストールは非常に簡単です。コミュニティベースの開発も盛んで、数多くのプラグインが開発されており、それらもダッシュボードからインストールが可能になっています。
Pythonプロジェクト用にもいくつかプラグインが存在していますが、その中でもShining Pandaはtoxが使いやすくなるので便利です。あるいは普通にPython Pluginを使えばよいでしょう。
Travis CI
Travis CIはGitHubでホストしているレポジトリを継続ビルドしてくれるサービスです。発表時現在はGitHubしかサポートしていないため、社内プロジェクト等だと利用は難しいかもしれません。
Pythonを含め14種類の言語が利用可能で、設定は .travis.yaml ファイルに書くだけ。まずはTravis CIの機能としてpy.testを走らせる例。
language: python python: - "2.6" - "2.7" - "3.1" - "3.2" install: - pip install -r requirements.txt --use-mirrors script: - py.test test
またtoxを利用している場合には次のようにtoxを走らせる指定をするだけ。
language: python install: - pip install tox script: - tox
ドキュメントの管理
ドキュメントはPythonコードとの連携のしやすさや、既存のreStructuredText資産を活かす意味でSphinxを利用します。手元では上記で触れたローカル開発環境に入れたSphinxでビルドを行います。Sphinxのインストールに関してはSphinx-Users.jpのサイトが詳しいので割愛しますが、``sphinx`` パッケージをインストールするだけです。
統合環境ではCIツールにてビルドを行うか、別途ドキュメント用ビルドツールを利用します。
- Jenkins
- ReadTheDocs
Jenkins
Jenkinsを利用する場合には、継続テストの場合と同様にドキュメントに更新があるごとにビルドを行うのが良いでしょう。Jenkinsの設定次第ですが、一番簡単な方法はJenkins用のワークスペースをそのまま公開することです。
大人数で閲覧する可能性がある場合はJenkinsでドキュメントをビルドする際に、専用Webサーバのドキュメントルートに
コピーするようなフローを用意してもいいでしょう。
ReadTheDocs
ReadTheDocsは2010年のDjango Dashで作成されたドキュメントホスティングシステムです。Sphinxプロジェクトを検知し、有名なVCSと連携してドキュメントがプッシュされると自動でビルドを行います。PythonだけでなくPHPやC++など多くの言語で開発が行われているプロジェクトのドキュメント公開に利用されており、PSFも出資しています。
現在、サービスとしての http://readthedocs.org/ と、パッケージとしてのReadTheDocsが存在します。オープンソースのものであれば前者を利用するのが良いでしょう。後者はまだ不完全ではありますが、自前でホスティングすることも可能です。執筆現在は最新版をビルドするとsyncdbするところでコケますので注意。
参照
参考資料
- Web
- 2012.05版 Python開発のお気に入り構成(ポロリもあるよ) - YAMAGUCHI::weblog
- 継続開発のススメ
- PEP 8 -- Style Guide for Python Code
- pythonz(pythonbrew)に関する私見
- Pythonモジュールの配布
- 2009/12/05 distutils, setuptools, distribute, pip, virtualenv, buildout
- PYTHON PACKAGING (PyFes 2012.03 発表資料)
- virutualenvとvirtualenvwrapperとpipを使う - YAMAGUCHI::weblog
- 26.9. venv — Creation of virtual environments — Python v3.4.0a0 documentation
- PEP 405 -- Python Virtual Environments
- Python3.3のvenvを試す - YAMAGUCHI::weblog
- AutoQA nose pytest comparison
- データ駆動テストを nose と pytest でやってみた
- Jenkinsでtox経由のpytestの結果を受け取るように設定する - YAMAGUCHI::weblog
- Travis CIでtoxを実行してみる - 偏った言語信者の垂れ流し
- Sphinx-Users.jp
- ReadTheDocsでSphinxホスティングは磐石(になる予定) - YAMAGUCHI::weblog
- 書籍
![エキスパートPythonプログラミング エキスパートPythonプログラミング](http://ecx.images-amazon.com/images/I/51wSTTIQtgL._SL160_.jpg)
- 作者: Tarek Ziade,稲田直哉,渋川よしき,清水川貴之,森本哲也
- 出版社/メーカー: アスキー・メディアワークス
- 発売日: 2010/05/28
- メディア: 大型本
- 購入: 33人 クリック: 780回
- この商品を含むブログ (88件) を見る
原著はこちら
![Expert Python Programming Expert Python Programming](http://ecx.images-amazon.com/images/I/51yEgqyNZvL._SL160_.jpg)
- 作者: Tarek Ziade
- 出版社/メーカー: Packt Publishing
- 発売日: 2008/09/30
- メディア: ペーパーバック
- クリック: 58回
- この商品を含むブログ (3件) を見る
![Pythonプロフェッショナルプログラミング Pythonプロフェッショナルプログラミング](http://ecx.images-amazon.com/images/I/41bZDMzzeTL._SL160_.jpg)
- 作者: ビープラウド
- 出版社/メーカー: 秀和システム
- 発売日: 2012/03/26
- メディア: 単行本
- 購入: 6人 クリック: 760回
- この商品を含むブログ (25件) を見る
- ツール
- Homebrew — MacPorts driving you to drink? Try Homebrew!
- The MacPorts Project -- Home
- saghul/pythonz · GitHub
- pip
- distribute
- virtualenv
- virtualenvwrapper
- zc.buildout
- nose
- py.test
- unittest
- tox
- buildbot
- Jenkins
- Travis CI
- Sphinx