2014-02-08

pyenv と tox で複数バージョンの Python に対応したライブラリ開発

生まれてはじめて PyPI にコードを登録した。Python 2.7 と 3.3 で使えるようにするにあたり、ライブラリの実装とは直接関係ないところで、とまどった。現時点での手順を記録しておく。

以下を前提とする。

  • OS X 10.9.1 (Mavericks)
  • homebrew でパッケージを管理
  • pyenv, pyenv-virtualenv で OS 上の Python 環境を管理
  • PyPI に登録するライブラリは Python 2.7 と 3.3 に対応

まず始める

shimizukawa によるハンズオン資料公式ドキュメントを併読しながら進める。基本的な作業はハンズオンでだいたい分かる。とはいえ、あなたが持っているライブラリは、必ずしもチュートリアルどおりではないだろうから、公式ドキュメントのガイドが必要になるだろう。

ところで、ナウなヤングは egg じゃなくて wheel を使うらしい

pyenv と pyenv-virtualenv をインストールする

pyenv は先週まで存在すら知らなかった。肉の日生まれの wozozo が使っているらしいので、試すことにした。まずインストールする。

$ brew install pyenv pyenv-virtualenv
$ cat >> ~/.zshrc
export PATH=$HOME/.pyenv/bin:$PATH
if which pyenv > /dev/null; then eval "$(pyenv init - zsh)"; fi

pyenv は複数の Python インタプリタをインストール/アンインストールするツールだ。pyenv-virtualenv は、pyenv と virtualenv を一緒に使いやすくする。実際に使ってみる。

$ pyenv install 2.7.6
$ pyenv virtualenv 2.7.6 foo-27

ひとつめのコマンドで Python 2.7.6 をインストールする。通常 ~/.pyenv/versions/2.7.6/bin/python にインストールされる。他にも pip なんかも入る。

ふたつめのコマンドで、Python 2.7.6 をベースに virtualenv を作る。通常 ~/.pyenv/versions/foo-27/bin/python に構築される。pip の他に activate なんかも入る。

同様に Python 3.3 をインストールして、仮想環境を作る。

$ pyenv install 3.3.3
$ pyenv virtualenv 3.3.3 foo-33

普段は Python 2.7 で作業しているので、おそらく foo-33 環境は不要だ。Python 3.3 については、tox が virtualenv を別途作ってくれる。けれど、カジュアルに pip とかしてしまうと、元の環境を壊してしまう。元の環境は綺麗にしておきたいので foo-27 と foo-33 環境を作る。

つづいて、プロジェクトで foo-27 と foo-33 う使うように設定する

$ cd /path/to/foo
$ pyenv local foo-27 foo-33
$ cat .python-version
foo-27
foo-33

pyenv local X Y を実行すると、そのディレクトリで使う Python 環境を設定する。ここでは foo-27 と foo-33 だ。

順序には意味がある。python コマンドを発行した時には、foo-27 環境の Python が呼び出される。

そして foo-27 と foo-33 の両方を指定する必要がある。後述する tox は python2.7 や python3.3 というコマンドを実行する。このとき pyenv local で指定された環境を探しに行くからだ。pyenv local foo-27 だと python3.3 が見つからないというエラーがでる。

ref. Using tox with pyenv #92



tox を設定する


$ pip install tox pytest
$ pip freeze | grep -v wsgiref > requirements.txt

wsgiref を含まないようにしている。理由は後述。

tox を使うための設定ファイルは以下のとおり。

$ cat > tox.ini
[tox]
envlist = py27,py33

[testenv]
deps = -rrequirements.txt
commands=py.test


envlist で py27 と py33 を指定しているため、このディレクトリ以下で、ビルドやテスト時に python2.7 と python3.3 を呼び出す。

tox.ini ファイルで、Python 2.7 インタプリタをフルパスを指定できる。だが、やらない。小さなプロジェクトだけれど、自分のところでしか動かないような設定にしたくないからだ。

tox を実行


$ tox

Python 2.7 用に virtualenv して、インストールして、ビルドして、テストを実行。Python 3.3 も同じ。

requirements.txt に wsgiref が含まれていると Python 3.3 で以下のようなエラーが出る。


Downloading/unpacking wsgiref==0.1.2 (from -r requirements.txt (line 7))
(...)
  File "./ez_setup/__init__.py", line 170

    print "Setuptools version",version,"or greater has been installed."

                             ^

SyntaxError: invalid syntax


PyPI へ登録する


$ python2.7 setup.py sdist bdist_egg upload
$ python3.3 setup.py bdist_egg upload

これで登録はできるが、こういう呼び出し方でいいのか自信がない。


まとめ


  • はじめて setup.py を書いた。
  • ヤク刈り、とは言わないけれど、地味に解決すべきことがことがあった。
  • 明日は肉の日である。