Upload
atsushi-odagiri
View
6.797
Download
0
Embed Size (px)
Citation preview
今年はPython3.3!そろそろ乗り換えモードじゃない?
BPStudy #54小田切 "aodag" 篤
お前誰よ?
小田切篤@aodag とある代々木の会社のエンジニア
http://facebook.com/aodaghttp://aodag.posterous.com
アジェンダ
なぜPython3?Python アドベントカレンダー2011 (Python3)Python3対応奮闘記Python3対応に役立つツールPython3対応の勘所
Python3って?
Pythonのバージョン3後方互換性のない変更を含む
Python2.6 Python3.1Python2.7 Python3.2と並行してリリースされてきた
今年の3月にPython3.3a1のリリースが予定されている
なぜPython3
Python2系は2.7で終わりもうPythonへの機能追加はPython3でしか行われない
Python3は単なるメジャーバージョンアップ
Python3でうれしい?いつかはPython3になってしまう。Python3対応は必然。
Python3対応に手を出すわけ
去年の夏にフォームライブラリを調べた(PyConJP 2011で発表)したが、Python3に対応したものがまったくないことが気になっていた
Python3対応に手を出すワケ
今ならPython3対応することで、オープンソースコミュニティに貢献しやすい。(大半が機械的な作業なので、実はローカライズについで手が出しやすい)
Python3対応奮闘記
ある日、ある雪山の開発合宿、あるIRCで
aodag: Python3やってるひとー。フォームライブラリ何使ってる?other: Python3対応してるフォームライブラリないよmcdonc_: deformとcolander対応する予定だけど、優先度高くないよ。
※ mcdonc_はpyramidの主要開発者です
aodag: deformとかなんで2.4とかまだサポートしてるのん? mcdonc_: ちゃんとした理由はないよ。3対応するなら2.6以降だけのサポートでいいね。 aodag: pyramidと同じようにワンソースアプローチだといいね。 mcdonc: それでうまくやってけそうだからね。
mcdonc_: Start Hacking ;)
(え、俺がやるの....?)
ということで
pylonsprojectとrepoze、Paste の以下のライブラリについてpy3対応
● peppercorn リリース済● colander リリース済 ● deform リリース済● repoze.who 作業中
やろうかなと思うもの● pyramid_who● pyramid_rpc● PasteScript
現在Python3対応しているライブラリ
http://pypi.python.org/pypi?:action=browse&c=533&show=all
SQLAlchemylxmlPyQtbottlepyramidSphinxnumpy/scipyipython...
Python3対応のアプローチ(1)ワンソースアプローチ
2to3変換やバージョンごとのモジュール切り替え
を行いません
Python3対応のアプローチ(1)ワンソースアプローチ
Pylons、repozeはこの方法
2系は2.6以降のサポートにします2.5以前は文法の差異を吸収できませんtoxにより、対応バージョンのテストを一度に実行できるようにします
3系は3.0,3.1は無視してもかまいません。
今現在Python3に手を出すような人は
3.2に移行してます。
Python3対応のアプローチ(2)2to3を使う方法
2to3を使ってソースを変換する
SQLAlchemyはこの方法
setupで、use_2to3=Trueにすれば、インストール時に2to3でコード変換してくれます
2to3
変換後にちゃんと動くかは、やはりテストが必要。開発中に2to3すると、ソースを直接書き換えられてしまう。toxで2to3変換後のソースをテストするにはコツが必要。
Fuckin' 2to3 !
2to3は使いたくない!
使いたくないワケ
テストコードも2to3するの?変換したテストコードで変換後のテスト...怖い><
ws_comma_fixer が重い
Python3対応の準備 ツールをそろえる
Python実行系の各種バージョンをそろえる
対応させたいバージョンはすべてそろえましょう
Python3対応の準備 ツールをそろえる
toxvirtualenvnosepytestdistributecoverage
tox - 対象バージョン全テスト
[tox]envlist = py26,py27,py32,pypy
[testenv]deps = nosecommands = nosetests []
SIX - 汎用互換ライブラリ
pylonsproject内では個々のパッケージでcompat.pyを作ってますが、汎用的なものをまとめたライブラリにsixがあります。
すでに誰かやってないか聞く
もしかしたら、もう誰かやってるかもしれないML, IRC, Twitter などで聞く
多分いないので、聞いてしまったことにより、自分がやることになります。
対応バージョン範囲を確認する。python2.5以前を切り捨てるかどうかがポイント切り捨てられないなら2to3を使うか、ダーティハックです。
Start Hacking ;)
手順(?) ソースを取り寄せる
pylonsprojectはgithubにリポジトリがあるのでとても楽でした。githubマジ神
ブランチを切ります
git checkout -b py3k
プロジェクトのやり方にあわせましょう。
テスト環境作成
ひとまず無難なところで2.6か2.7で作業環境を作ります。
mkvirtualenv -p python2.7 testenv
テストツールインストールpip install tox nose coverage
依存ライブラリなどインストールpip install -e .
手順(?) 既存のテストを確認する
そもそも2系で動くテストなければ
はじまりません。
なければテストを充実させるところからです。
既存のテストを確認するカバレージの確認
コマンドラインオプション
nosetests --with-coverage --cover-package=テスト対象
既存のテストを確認する noseの設定
setup.cfg でコマンドラインオプション固定
[nosetests]with-coverage = 1cover-package = テスト対象
toxを設定する
;; tox.ini
[tox]envlist = py26,py27,py32,pypy
[testenv]deps = nose coveragecommands = nosetests []
toxを動かす
コマンド自体は簡単です
$ tox
1回目は対象バージョンすべてのvirtualenvを実行するので時間がかかります。
多分python3で動かないことを確認できるでしょう。
依存ライブラリを確認する
py3k対応していないライブラリをどうするか?
●依存からはずして代替ライブラリに変更●依存からはずして、同等機能をついか●そのライブラリをpy3k対応する
○本当に対応する○コードをとりこむ
●諦める
互換モジュールを追加する
●独自にcompatモジュールを作る●sixを使う
compatモジュール
バージョンフラグpy3 = sys.version_info > (3,0)
compatモジュール
名前の変わった標準ライブラリ
StringIOurllib周りcookieやconfigparser, httplib
compatモジュール
str, bytes の差異を吸収するユーティリティ
binary_typestext_types
text_bytes_
などをpython2用とpython3用にそれぞれていぎ
文法の非互換に立ち向かう
2大文法エラー
●例外ブロック●ユニコードリテラル
例外ブロック
old except Exception, e:
new 2.6から使えるexcept Exception as e:
ユニコードリテラル
ユニコード文字列リテラルu"日本語"
compatユーティリティでラップする
text_("日本語")
importエラーをなおす
よくあるimportエラー
●相対import●名前が変わった標準ライブラリ
名前が変わったものなどcompat内で解決import先をcompat経由に変更する
相対import
2系では相対import優先。3系では絶対import優先
import amodule
どちらでも相対import優先
from . import amodule
コード、テストを修正する
ここまでくればいつもどおり!いきなり80%のテストが失敗しますが、心折れずに進めましょう。
Python3対応の勘所(1) iterator
組み込み関数がのきなみiteratorに対応zipもfilterもrangeもlistではなくiteratorを返す
それぞれのiterator版だった、izipやifilter, xrangeなどは消滅
で す が
len(zip((1,2,3), ('a', 'b', 'c')))
3系だとNG!やりたければlistコンストラクタを明示的に呼び出す
len(list(zip((1,2,3), ('a', 'b', 'c'))))
Python3対応の勘所(2) strとbytes
Python3の文字列はユニコードPython2のバイト配列に対応するものはbytesに変更
Python2でなんとなく使ってたバイト文字列とユニコード文字列の違いを意識する場面が増えた
多くの関数、ライブラリがstr前提に
json.loads strしか受け取れないjson.load strを返すファイルライクオブジェクトじゃないとだめ
open関数が返すオブジェクトはstrを返すファイルライクオブジェクト
StringIOとBytesIO
ioモジュールに統合
bytesの注意点
bytesとstrは結合できない
NG b'a' + 'a'
2系では自動変換されてました
bytesの注意点
%演算子を使ったフォーマットが使えない
NG b'%d' % 10
bytesの注意点
コンストラクタ
3のbytesbytes(source, encoding, errors)
2のころのstrstr(object)
bytesの注意点
2のころ
>>> str(b'a')'a'
3だと
>>> str(b'a')"b'a'"
要するに
3系のbytesは2系のstrと
互換ではない
Python3対応の勘所(3) strがちゃんとしたiteratorを実装している
__next__や__iter__が実装されiteratorとして正しいインターフェイスとなった。
し か し2系で使われていたバッドノウハウ__iter__ の有無でlistとstrを振り分けるは、もう使えません。ちゃんとisinstanceを使いましょう。
Python3対応の勘所(4)basestringがなくなった
2系のstrとunicode共通のスーパークラスだったbasestringがなくなりました。
isisntance(s, basestring) はできません
バージョンチェックで str_typesを作って対応2系のstr_typesstr_types = (str,unicode)3系のstr_typesstr_types = (str,)
Python3対応の勘所(5)相対importの罠
2系の場合と3系の場合で優先順位が違う
2系 相対importが優先3系 絶対importが優先
a/__init__.pya/a.py
3系で a/__init__.py で import aをやると自分をimportする!この場合は、from a import a か from . import a としましょう。
相対importの罠にはまったライブラリ
iso8601
最終リリース(2007年)からissuesも放置状態...作者への連絡方法も分からず、py3k対応のスタンスも確認できない
MITライセンスだったので、ソース取り込みで対応
例外文法
とくにキャッチする部分
2系のみexcept Exception, e:
2.6以降と3系except Exception as e:
どのバージョンでも動く? 2.4や2.5でも3.2でも動く。except Exception: e = sys.exc_info()[1]
多分一番ポータブル!でも、なんかいや
まとめ
鶏が先か卵が先か。せっかくなので提供する側になりたいです。
テストがすでにそろってる状態であれば、Python3対応は機械的に進められます。テスト大事。
当然Python3での変更を調べることになります。Python3を仕事で使う前にオープンソースプロジェクトに貢献しつつ、はまりどころを事前に知ることができます。しかも、世界レベルの開発者からのアドバイスまでもらえます。
http://www.voidspace.org.uk/python/articles/porting-mock-to-python-3.shtml
http://pypi.python.org/pypi/six