読者です 読者をやめる 読者になる 読者になる

モラトリアムこじらせた

大人に成り切れない自分を自覚してウジウジと自分探しを延々と繰り返しつつ、気付いてみれば社会人になってからもう何年も経っちゃってて、そういえばローンとかも組んじゃってて、考えてみれば色々と取り返しのつかない年齢になっちゃってて、給料は上がらずリストラに怯えつつ、焦ってみても慌ててみても、やっぱり心に引っ掛るものが何なのか分からず、やっぱりウジウジ自分探しなんかしちゃったりしてる…、そんなモラトリアムをこじらせたあ・な・た(私)にお贈りする技術ブログ

Python 2 と Python 3 のどちらを使って開発すべき?

さて、いきなりですが、Python 本家の Wiki にある Should I use Python 2 or Python 3 for my development activity? という文書を日本語に翻訳してみました。

「そういえば Python 3 って出てもう何年も経ってるんだよなぁ。でもずっと Python 2 系使ってたし 3 って互換性ないらしいし、よく分からんし怖いよなぁ…」

って風に Python こじらせちゃってるあなた(私)には、特に有益かと思います。

誤訳や間違いなどのご指摘とか、もっとこうした方がいいとか、その他コメントなどありましたら、是非このブログのコメント欄をご利用ください。 Twitter@nyagao 宛にメッセージ送って頂いても構いません。

では、以下、その翻訳です。(wiki の last edited 2014-03-16 15:19:13 版を元にしています)


Python 2 と Python 3 のどちらを使って開発すべき?

違いは何?

簡単に言えば、Python 2.x は過去の遺物であり、Python 3.x は今現在そして今後の姿である。

Python 3.0 は 2008 年にリリースされた。 2.x 系の最後のバージョンである 2.7 は、開発を終了した 2.x 系のサポートを延長する名目で 2010 年中盤にリリースされた。 2.x ブランチは、それ以後メジャーリリースが行なわれる予定は無い。 3.x は、現在積極的に開発が進められている状況にあり、この 4 年以上で既に安定版がいくつかリリースされている。 2012 年にリリースされた 3.3 もその一つ。 次回のリリースは 2014 初頭に Python 3.4 が登場する予定 (訳注: 2013/3/16 にリリースされた)。 このことは、例えば、新しい標準ライブラリは全てデフォルトで Python 3.x 用にしか改善されていかない、ということを意味する。

Guido van Rossum (Python の作者) は、Python 2.x 系を適切にきちんと整理することに決めた。 この際、後方互換性については 2.x 系の場合よりもこだわらないことにした。 最もドラスティックな改善点は、Unicode のサポート方法が良くなったことと (全ての文字列はデフォルトで Unicode になった)、bytes 型と Unicode 型がマトモに分離されたことが挙げられる。

更に (print 文、exec 文、切り捨て除算などの) コア言語の幾つかの点が修正され、新規参入者に分かりやすく学習しやすく、言語の他の部分との一貫性が高くなった。 また、古臭い不快な要素は削除された (例えば、全ての class は今は新しいスタイルだし、range() は 2.x のようなリストではなく、メモリ効率の良い iterable を返す)。

What's New in Python 3.0 は、言語自体の主な変更点や、既存の Python 2.x 系コードと非互換性の原因になりそうな部分について概要を知る良い文書となっている。 Nick Coghlan (CPython の中心的な開発者の一人) も、新バージョンへの移行に関して比較的規模の大きい FAQ を作成している。

しかしながら、Python のエコシステムの広がりにより、ここ数年でかなりの量の良質なソフトウェアが蓄積されてきた。 3.x で後方互換性が壊されたことのマイナス面は、そういったソフトウェアに (特に企業内で自社開発したソフトウェアに)、まだ 3.x で動作しないものがあるということだ。

どのバージョンを使えばいい?

あなたが使うべきバージョンは、あなたが何をしたいのかという点にほぼ依存している。

もしあなたがやりたいことが、まさしく Python 3.x で実現できるなら、それは素晴しい! ただし、ちょっとしたマイナス面がある。たとえば、ライブラリのサポートがすこし弱い((メンテナンス中のパッケージに囲まれている^1。 また、現行の Linux ディストリビューションMac はほとんど、まだ 2.x をデフォルトとしているのも事実。 しかし、Python 3.x はもう既に言語として使える状態にある。 あなたのコンピュータに Python 3.x をインストールし (この文書を読んでいる人なら自分で何か開発したり環境を弄ったりできるのでインストールは簡単なはず) 、そしてあなたが Python 2.x モジュールの必要ない状況でコードを書いているのであれば、3.x は素晴しい選択となる。 しかも、ほとんどの Linux ディストリビューションは既に 3.x がインストール済みでエンドユーザーが利用できる。 Python 2 を段階的に廃止しようとしているディストリビューションもある^2

特に、新しいプログラマ達に Python を教えようとしている講師の方々は、最初に Python 3 を教えて、その後 (必要であれば) Python 2 との違いを教えたい、と思っているかも知れない。 というのも、Python3 では、Python 2 を初めて学ぶ人が不必要につまづく原因となる多くの変なところが取り除かれているため。

しかし、いくつかの主要な問題により、Python 3 ではなく Python 2 を使う必要に迫られる場合もあるだろう。

  • まず、自分で弄れない環境に対してデプロイする場合は、利用可能な複数のバージョンから自由に選べるのではなく、特定のバージョンを使わざるを得ないかもしれない。
  • 次に、サードパーティのパッケージやユーティリティ等を使う場合、Python 3 版がリリースされておらず、また移植が単純にできるものでなければ、そのパッケージを使える状態にしておくために Python 2 を使う選択をするかもしれない。

特に、まだ Python 3 をサポートしていない有名なモジュールには Twisted (ネットワーク等のアプリケーション用) や、gevent (Twisted と同様のネットワークライブラリだが明示的な非同期スタイルではなく micro-thread を使っている) がある。

こういったライブラリにはほとんど、3.x 対応の作業をしてる人々がいる。完成の度合いは色々だが大抵は作業中という状況にある。他の作業よりも優先することだと考えているライブラリもある。 たとえば Twisted は、主に製品サーバー群に主眼を置いており、そこでは古いバージョンの Python をサポートすることが重要になっているが、言語に大きな変更がある新バージョンへのサポートはもちろんのこととしている。 (Twisted は 3.x への移植が決して単純な話ではない主要パッケージの最たる例である)

GUI アプリケーション開発のために、Python 3 には TKinter が同梱されている。 また、Python 3 がリリースされたほぼその日から PyQt がサポートしている。 2011 年には PySidePython 3 サポートを加えた。 GTK+ GUI は、PyGtk の後続で Python 3 をサポートしている PyGObject を使って作ることができる。

他にも多くのメジャーなパッケージが Python 3 に移植されている。たとえば:

  • numpy (複雑な計算用)
  • Django, Flask, CherryPy, Pyramid (ウェブサイト用)
  • PIL (画像処理モジュール) はフォーク版の Pillow に取って替わられ、Python 3 をサポートしている
  • cx_Freeze (依存関係をもとにアプリケーションをパッケージ化する)
  • py2exe (Windows 用のアプリケーションパッケージ化)

もし Python 3.x を使いたいのに、依存関係のために躊躇しているのなら、恐らく最初に調査することから始める価値があるだろう。 この文書は作成中の状態であり、この wiki ページはもう古くなっている可能性もある。 さらに、Python 2.6 以上と Python 3.3 以上の両方がサポートする大きな共通部分を用いれば、沢山の現代的な Python のコード、特にウェブや GUI フレームワーク間での相互運用のために書かれたコードはアプリケーションにバイナリとテキストを正しく分離することを強制しており、そのようなコードは、ほとんど変更することなく Python 3 上で動かすことができるはずである。 (名前の変更を扱うために six compatibility module の助けが必要になるかもしれないが)

たとえ公式の Python のドキュメンテーションチュートリアルPython 3 向けに更新されたとしても、ウェブや参考書籍には、多くは更新されていくだろうが、まだ Python 2 で書かれた文書 (や例) がたくさん存在する。 そのため、Python 3 を使って何かしようとすると、ちょっとした修正が必要になる可能性がある。

単に Python 3.x を使いたくないという人もいる。それはその人の権利。 しかし、彼等はマイノリティである。

IronPython, Jython, PyPy など (その他にも Python プラットフォームやコンパイラ実装が多数存在する) Python の他の実装を使いたいのであれば、Python 3 をサポートしているのは稀であることに注意すべき。 もし他のシステムとの統合やパフォーマンスのために、そのような実装を選ぶのに興味があるのなら、この事実はその選択に影響を及ぼすかもしれない。

でも、2.x を避けたいと思うことにならない? 古い言語でたくさん間違いもあるし、それを取り除いたのが新バージョンなわけでしょ。

ええと、全てがそうという訳ではない。 3.0 と 3.1 におけるさほど破壊的ではない改善点がいくつか、それぞれ 2.6 と 2.7 にバックポートされている。 バックポートされた機能の詳細については、What's New in Python 2.6What's New in Python 2.7 を参照。

3.x でしか利用できず 2.x 系にバックポートされる予定が無い機能を、すべてを網羅しているわけではないが、以下に列挙する。

  • 文字列がデフォルトで Unicode
  • Unicode とバイト列とを明確に分けた
  • 例外チェーン
  • 関数アノテーション
  • keyword-only 引数のための文法
  • tuple の unpack 機能の拡張
  • 局所変数ではない変数の宣言方法

また、言語の進化は、コアの文法や意味の変更に留まらない。 標準ライブラリも 3.x で多くの改善がなされているが、そのまま Python 2 にバックポートされるという予定はない。 たとえば What's New in Python 3.0 を参照のこと。 それでも、多くの標準ライブラリはの改善は PyPI を通して利用することもできる。

とは言うものの、ちゃんと書かれた 2.x のコードは、大体は 3.x 的なコードになり得る。 これは色々な意味があるが、 新しいスタイルの class を使うこと、 print 文の古く廃止された難解なおまじないを使わないこと、 可能な場所で lazy iterator を使うこと、 などが挙げられる。 具体的な例としては: 良い 2.x コードは典型的に range ではなく xrange を使っている。 xrange の実装は Python 3.x の range の実装の開始地点だった (しかし range は Python 3 ではずっと良いものになっている。sys.maxint より大きい値を扱えるので) 。 注意すべきは、Python 3 には xrange() が含まれないということ。

何よりもまず、2.x 対 3.x という問題が大きくならないような、良いコードを書くことに注力することをお勧めする。 具体的には、十分なユニットテストスイートを書くとか、Unicode を正しく扱うとか。 (Python 3.x は 2.x と比べて、Unicode 対 bytes 問題に関してかなり厳しめになっている。 これは良いことだと見なせる。 ただ、ソフトウェアパッケージを移植するのが非常に面倒になるけども)

Python 3 を使いたいのに、Python 2.x しか対応していない小さいライブラリがあって、それを使いたい。Python 2 に逆戻りすべきか、そのライブラリを諦めるべきか?

Python 3 に対応した代わりのパッケージが見付からないなら、以下のことを考えてみる必要がある:

  • そのライブラリを 3.x に移植する
  • もし移植が本当に困難だとわかったら、そして、他の依存関係もすべて 2.x にあるのであれば、2.x での開発を考慮すべき。 既に述べたように、良い 2.x のコードは典型的に、依存関係にあるものがすべて 3.x 向けに移植されればすぐに、苦労なく 3.x に移行することができるだろう。
  • その機能が本当に、そんなに重要かどうか判断する。もしかしたら、それをドロップしても良いのでは?

理想的な状況は、あなたがそのライブラリを 3.x に移植してみるということだ。 既に誰かが移植を始めていることもよくある。 そうでなくても既存のプロジェクトメンバーは大抵喜んで手助けしてくれるだろう。 特に、移植作業というものは元のソフトウェアのバグを発見することが良くあるので、元のソフトウェアと 3.x 移植版の両方の品質向上となるからだ。 移植は常に簡単という訳ではないが、通常は自分でスクラッチから書くより簡単である。

この Python 2 porting guide には、移植をどう進めることになるかが説明されている。 基本的な考え方は、2.x 版のライブラリを取ってきて、すべてのユニットテストPython 2 で "-3" オプションを付けて走らせ、warining が出ずに通るかどうかを確認すること。 もしテストが失敗したり warning を出す場合は、ソースを変更して再度試す。 (この段階で古い Python との互換性を失う必要があるかもしれない) もし "-3" スイッチをつけて warning も出ずにコードが動くようになったら、Python 3 で動くかどうか試してみる。 最良のケースは、そのコードが「単に動いた」とき。もうそのコードは現代的な Python 2 の作法で書かれており、Python 3 とも互換になっている。 従って、この時点で「移植」は完了したと言える状態になっているかもしれない。

まだ Python 3 上でテストが失敗するなら、標準ライブラリの 2to3 ユーティリティを使うことで、Python 3 で動作するバージョンを自動生成することもできる。 別の手段として Armin Ronacher の python-modernize ユーティリティは、Python 2.6 以上と、3.2 以上か 3.3 以上のどちらか (コマンドラインオプションで選択) との共通部分をターゲットにする。(もし後者を使うなら Python 2 でもテストが通るか確認することが重要!)

どちらのアプローチも、単一の 2.x のコードベースから、2.x と 3.x の両方のサポートを実現可能にする。 これは 2.x と 3.x 系の別々のブランチを平行してメンテナンスするよりもずっと簡単である。 (Python コアの開発者にちょっと聞いてみればいい。彼らはもうこの数年間、平行メンテという状況に置かれてしまってるのだから!)

もし自動変換や近代化(modernisation)でテストが失敗するなら、Python 2 から 3 でセマンティクスが変わってしまった部分にコードが依存しており、コンバータが自動的に処理できないか、"-3" スイッチでも検出されなかった可能性がある。 こういった問題は稀ではあるが、まだ存在する可能性がある。 もしこういった問題に出くわしたら、CPython に対してバグ報告し、新しい "-3" の warning を追加してもらうようリクエストする価値がある。

もし C による拡張モジュールが絡んでいて、プロジェクトが Cython や cffi や SWIG のような Python 2 と 3 の違いを自動で処理してくれるような wrapper generator を使っていないのであれば、移植の状況はもっと複雑になってくる。 しかし、そのような状況であっても、同等のパッケージを自分自身で作り上げるよりは、移植するほうがまだ簡単だと言えるだろう。 extension porting guide に主な変更点が記されている。

その他にも、もっと深く掘り下げたガイドがこの Wiki に置かれている: PortingPythonToPy3k, PortingExtensionModulesToPy3k

3.x で何か書くことにしたけど、それを 2.x しか使えない人が使いたがってる。どうすればいい?

"2to3" は 2.x ソースコードから 3.x コードを生成するツールだが、その他に "3to2" というツールもある。 これは 3.x のコードを逆に 2.x のコードに戻すためのもの。

理論上は、2.x から 3.x の変換よりも上手く変換できるはずである。 なぜなら、3.x には、コンバーターが扱うことになる重箱の隅を突くような汚いケースが 2.x よりも多くはないから。 (そういったものを可能な限り駆除することが、結局、後方互換性を壊すことになった大きな理由の一つだったのだ!) しかしながら、3.x にしかない機能に大きく依存したコード (関数アノテーションや tuple の unpack 機能の拡張など) は、うまく変換できないことがある。

また、現時点で 3to2 は 2to3 と比べてあまり使い込まれてないとも言えるだろう。 そのため、あちこち荒削りな部分に遭遇するかもしれない。 しかし、3.x でコードを書きたいのであれば、もちろん調査してみる価値はある。

Python 2 と Python 3 を共通のコードベースでサポートする

Python 2.6 以上と Python 3.3 以上の共通部分は極めて大きい。 Unicode リテラルを表わす "u" プレフィックスが Python 3.3 で復活したことは、Python 2.6 以上で書かれた意味的に正しいコードを、大部分において Python らしさを残しつつも更に、Python 3.3 以上とソース互換にできることを意味する。 主な違いは、Python 2 と Python 3 で違う名前になっているものがいくつかあり、それらを扱うために違う場所から import する必要があること。

従って、six compatibility package が、Python 2 と Python 3 を単一のコードベースでサポートするのに重要なユーティリティとなっている。

future compatibility package はまだβ版で、サポートしている Python のバージョンも six ほど多くない (six は 2.4 まで遡れるが、future は 2.6 までしかサポートしない)。 しかし future では、Python 2 互換のコードをもっと Python 3 の作法に近いスタイルで書くことができる。 (例えば Python 3 の bytes 型については、Python 2.x の 8-bit 文字列型に頼って微妙に異なる API が晒されてしまうのではなく、Python 2 で実際に bytes 型互換の機能を実装している)

どの標準ライブラリモジュールを使えば良いかを知るもう一つのキーポイントは、2.x の標準ライブラリのよりも新しいバージョンのバックポートが PyPI にあるかどうかという点だ。 以下に示すモジュールは、PyPI にあるバックポート版か、もしくは 2.7 か 3.x 用の標準ライブラリの追加分として役割を果たしているオリジナルのモジュールだ。(あるいは追加モジュールの着想となったものもある)

  • unittest2 (標準ライブラリの unittest のメンテナである Michael Foord 作、2.6 サポートのために大概必要になる)
  • mock (標準ライブラリ unittest.mock のメンテナである Michael Foord 作)
  • contextlib2 (標準ライブラリ unittest.contextlib のメンテナ Nick Coghlan 作)
  • configparser (標準ライブラリ configparser のメンテナ Łukasz Langa 作)
  • futures (標準ライブラリ concurrent.futures のメンテナである Alex Grönholm と Brian Quinlan の作)
  • argparse (標準ライブラリ argparse のメンテナである Steven Bethard 作、2.6 サポートのために大概必要になる)
  • faulthandler (標準ライブラリ faulthandler のメンテナ Victor Stinner 作)
  • cdecimal (標準ライブラリ decimal のメンテナ Stefan Krah 作)
  • ipaddr (標準ライブラリ ipaddress のメンテナ Peter Moody の作、Google の IP address を処理するモジュールで 標準ライブラリ ipaddress モジュールの設計に着想を与えた)
  • stats (標準ライブラリ statistics のメンテナ Steven D'Aprano の作)
  • enum34 (標準ライブラリ enum のメンテナ Ethan Furman 作)
  • funcsigs (Aaron Iles 作, function signature objects のバックポート)
  • shared namespace module for backports (Brandon Craig Rhodes 作)
  • backports.inspect (Tripp Lilley 作、追加の inspect モジュールの変更のバックポート、fucsigs をベースにしている)
  • backports.datetime_timestamp (Jason R. Coombs 作、datetime.timestamp メソッドのバックポートで、datetime オブジェクトを受けるモジュールレベルの関数)
  • backports.pbkdf2 (標準ライブラリ hashlib のメンテナ Christian Heimes 作、hashlib.pbkdf2_hmac のバックポート)
  • backports.ssl_match_hostname (Brandom Craig Rhodes と Toshio Kuratomi 作, ssl.match_hostname のバックポート)
  • backports.lzma (Peter Cock 作, lzma wrapper モジュールのバックポート)
  • lzmaffi (Tomer Chachamu 作, もう一つの lzma のバックポートで、cffi を使って PyPy JIT 互換性を高めている)
  • tracemalloc (標準ライブラリ tracemalloc のメンテナ Victor Stinner 作)
  • pathlib (標準ライブラリ pathlib のメンテナ Antoine Pitrou 作)

"backports namespace module" を使うメリットは、もし(自分の使っている機能の中に)標準ライブラリの機能のバックポートがあるとき、そのことがはっきり明示されるという点にある。 その上、適切な場合には、標準ライブラリ名と衝突することなくオリジナルのモジュール名を使うことができる、という点もある。

ActiveStatePython Cookbook に小さめの Python 3 追加モジュールがレシピとして載っている。

次のモジュールはバックポートではないが、バージョンを跨がって互換性があり、主要な標準ライブラリ API の置き換えとして使うことができる。

  • requests (HTTP と HTTPS の高レベル API。この requests 自身は様々な理由で標準ライブラリには取り込まれないだろう。 しかし、asyncio をベースにした同等のクライアント API が将来的に追加されると思われる)
  • regex (正規表現エンジンの代替で、最終的に 標準ライブラリに取り込まれることが大筋として承認されている。 しかし、取り込む詳細を詰めるために PEP が必要とされている)
  • lxml.etree (ElementTree XML API の代替の実装)

これらの Python 2 もサポートしているモジュールに加えて、 Python 3.4 で標準ライブラリに追加された ayncio モジュールは、もともと Python 3.3 用に PyPI モジュールとして開発されたものだった:

  • asyncio (優しい終身の独裁者 (BDFL) であり、標準ライブラリ asyncio のメンテナである Guide van Rossum の作。Python 3.3 で追加された "yield from" 構文が必要)

その他、Python 2 と Python 3 の選択の助けとなり得るリソース

脚注

^1

メンテナンス中のパッケージがまだある https://python3wos.appspot.com

^2
Arch Linuxpython を python3 にリンクを張っている。 UbuntuFedora はデフォルトを切り替えている。 https://wiki.ubuntu.com/Python/3, https://fedoraproject.org/wiki/Changes/Python_3_as_Default


日本語翻訳版 by @nyagao, 最終更新日: 2014-03-25 20:33


Dive Into Python 3 日本語版

Dive Into Python 3 日本語版

Python入門―2&3対応

Python入門―2&3対応

パーフェクトPython (PERFECT SERIES 5)

パーフェクトPython (PERFECT SERIES 5)

エキスパートPythonプログラミング

エキスパートPythonプログラミング

Pythonプロフェッショナルプログラミング

Pythonプロフェッショナルプログラミング

Python クックブック 第2版

Python クックブック 第2版

みんなのPython 第3版

みんなのPython 第3版