LoginSignup
12
14

More than 5 years have passed since last update.

Python3にすんなり移行できないから 2-3 互換を考えよう

Posted at

そろそろPython3移行どうしようかという話が社内でも出てきたので少し調べた話。

Python2系サポートは2020年まで

Python2系はサポートが2020年まで公式で発表されています。
(なお2.8はない模様)
現在の手持ちPython製プロダクトが2020年まで稼働しているかはともかくとして、
そろそろPython3への移行を視野に入れておいた方いい時期にさしかかっています。

まずどんな風に変わるか少し列挙

Python2.X Python3.X 2系記法で3系は動くか
print 'xxx' print('xxx') ×
xrange(1, 10) range(1, 10) ×
except Error, V except Error as V ×

rangeは3系ではxrangeの挙動になったようです。

見た感じ2系から3系へ移行と言ってもそこまで大きく変わるわけではありません。
細かい構文変更ぐらいです。(外部ライブラリが対応しているかは要チェック)

移行か互換か

サポート切れといってもそこまでは運用しなくてはならない、2系と3系で別々に実装するのも効率が悪い。
ということですっぱり2系を切り捨てて移行はできず、3系と共存する道を探すのが現実的です。
幸いPythonでは2系と3系は割と同居可能です。

移行の場合

せっかくなので移行ツールも

2to3

一括変換ライブラリとして 2to3 が用意されています。
Pythonに組み込まれているので外部からインストールする必要はありません。

Python3系のシンタックスに合うように構文や適宜インポートも整えてくれるようです。
2to3 に3系から2系へ変換する機能はありません。
でも 3to2 というサードパーティ製ライブラリもあるそうです。(いる?)
https://pypi.python.org/pypi/3to2

互換性を保つ

互換性を保つためにどんなことができるか紹介します。

2系で3系表記をするfuture

実行環境2系で3系の記法ができます。
http://docs.python.jp/2/library/__future__.html

print() で書けるようになります。

from __future__ import print_function
print ('hoge')

Unicodeを u'hogehoge' と書いていたのが u が不要になります。

>>> from __future__ import unicode_literals
>>> '日本語'
u'\u65e5\u672c\u8a9e'
>>> u'日本語'
u'\u65e5\u672c\u8a9e'

インポートが絶対インポート優先になる(説明が難しい)

from __future__ import absolute_import

あと3つ4つありますが、Python2.6以上だとあまり関係ないので省略。

six

互換性を保つライブラリも用意されています。six です。
2 * 3 = 6 で six らしいです。覚えやすいですね。
こちらは外部ライブラリです。
http://hhsprings.bitbucket.org/docs/translations/python/six-doc-ja/

pip install six

使い方はインポートして、2系と3系の互換性のない部分に使用するだけです。
実行時のPythonバージョンに応じて内部で使い分けてくれます。

例えば文字列系だと、

Python2 Python3 six
basestring str string_types
unicode str text_type
str bytes binary_type

iterable (collection)
iterable系は大体似た感じなのでよく使いそうな dict を見てみると、

Python2 Python3 six
iterkeys keys iterkeys
itervalues values itervalues
iteritems items iteritems

記法は2系に寄せた感じです。

結構な数のビルトインがsixで吸収可能です。

そもそも

2-3互換チートシートがあります!
http://python-future.org/compatible_idioms.html

楽に移行はできるのか

互換性を保てることはわかりましたが、対応箇所を一つずつ探して修正するのは馬鹿にならない工数です。
一括変換ライブラリがほしくなります。あるのでしょうか?

ありました!
https://github.com/python-modernize/python-modernize
sixも使って変換してくれるそうでなかなか期待できそうです。
ソースを少し覗いた感じでは、six や future があったので、これらを使っていい感じに変換してくれるのでは!?
別の機会に試してみたいと思います。
(今回は時間が足りませんでした。本当に申し訳ない。)
(試した方は先に記事を書くチャンスです!)

Python3のいいところ

移行の手間がかかりますが、Python3にすればこんないいこともあります。

型ヒント

http://docs.python.jp/3/library/typing.html
関数やクラス定義時に型指定ができます。

def greeting(name: str) -> str:
    return 'Hello ' + name

コンパイル言語と違い実行時チェックはできないものの、
開発時に引数の型がすぐわかるのはバグを未然に防ぐ意味で結構重要です。

順序付き辞書

入れた順番通りに取り出せる辞書です。
以前、並び順をvalueに入れ込んで取り出した後にソートとかした記憶もあるので使い道はありそう。

>>> from collections import OrderedDict
>>> od = OrderedDict()
>>> od['a'] = 1
>>> od['b'] = 2
>>> od['c'] = 3
>>> for k, v in od.items():
...   print(k, v)
... 
a 1
b 2
c 3

>>> od2 = OrderedDict()
>>> od2['c'] = 3
>>> od2['b'] = 2
>>> od2['a'] = 1
>>> for k, v in od2.items():
...   print(k, v)
... 
c 3
b 2
a 1

Python3.5からはさらに速くなってるそうですよ!

さらにPython3.6には非同期ジェネレータなども実装されるらしく夢が広がります。
サポート期限というネガティブな動機だけでなく、新機能のためにPython3対応、しましょう!

12
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
14