概要

OpenStack では Python 3 対応の作業が進められています。Python の開発サイト (https://www.python.org/) でもトップページで Python 3 の特徴を述べて Python 3 の使用を奨励している様です。本稿では、Python 3 への移行の理由と、具体的に Python 2.7 から Python 3.4 へのコード変換に必要となる情報について解説していきます。なお、本稿は移植に関して説明するもので、新機能については言及しません。

本稿執筆時の Python のバージョンは 3.4 です。2016年6月にバージョン 3.5.2 がリリースされています。

第 1 回 Python 3 への置き換えの事情

Python 2.7 のサポート

Python 2.7 のサポート期限は 2020年に延長されました (参考: https://www.python.org/dev/peps/pep-0373/)。
サポート内容は、重大なセキュリティバグぐらいで、それ以外のバグは基本的に Python 3 で修正する方向性のため、Python 3 からのバックポートも余り期待できない模様です (参考: https://www.python.org/dev/peps/pep-0466/)。

Python 3 の特徴

全体的に言語体系が整理された印象があります。主な特徴は以下の通りです。

 

  • 文字型の扱いが明確になった。
  • 文字コードが unicode ベースになった。
  • 直接リストを返さなくなった。
  • 似た機能が統一された。
  • 新しい機能として ファイル記述子の非継承、asyncio モジュールが追加された。

参考: What’s New in Python (日本語訳)

ディストリビューションの状況

各ディストリビューションと Python の対応バージョンについては以下の通りです。
括弧内はデフォルトではありませんがパッケージが提供されているものです。

 

  • RedHat
    – RHEL 6: Python 2.6
    – RHEL 7: Python 2.7

 

  • Ubuntu
    – Ubuntu 12.04: Python 2.7, (Python 3.2)
    – Ubuntu 14.04: Python 2.7, (Python 3.4)
    – Ubuntu 16.04: Python 3.4, (Python 2.7)

 

  • OpenSUSE
    – OpenSUSE 11.4: Python 2.7
    – OpenSUSE 12.3: Python 2.7, (Python 3.3)
    – OpenSUSE 13.2: Python 2.7, (Python 3.4)

Python の開発状況 (2016年12月現在)

 

 

リプレースの状況

Python 3 対応状況

Python 3 としては、Python 3.0 が 2008年 12月にリリースされて以来、時間が立つが移植作業はそれ程活発ではないように感じます。
代表的な Python ベースの下記のソフトを見るとサポートは半々ぐらいのようです。

 

  • Anaconda : Python2
  • Django : Python 2, 3
  • Mercurial : Python 2
  • OpenStack : Python 3対応中
  • Trac : Python 2.7
  • Zope : Python 2, 3

PyPI に登録されているパッケージで Python 3 対応のものはおよそ 18 % 程度(2015/9/4 時点) となっています。

移植が進まない要因

Python 3 への移植が進まない主な理由として、Python 2 と Python 3 の互換性の問題があります。
Python 2 は後方互換性に配慮していましたが、Python 3 では互換性を切り捨て、よりクリーンなコードを目指したため置き換えるのは大変な作業となります。また、Windows 2000 や OS/2、VMSなど、未サポートとなったOSもあります。
Python 2.7 のサポート期限について、当初は 2015年まででしたが現在は 2020年まで延長となったため、しばらくは安泰という見方もあり移植が進まない要因にもなっていると思われます。

第 2 回 移植に必要な処置

Python 2 で作成したコードを Python 3 でそのまま実行すると思ったより多くのエラーを目にするのではないでしょうか。前述のように後方互換を考慮しない方針のため、メソッドのリターン情報が変わったり、メソッドそのものがなくなったものもあります。Python 3 での主な変更点を以下に述べて行きます。

Python 2 で削除されたメソッド

別のメソッドで置き換えられるものと、メソッドとして提供されなくなったものがあります。

 

  • dict
    dict.iteritems()    →  dict.items()
    dict.viewitems()
    dict.iterkeys()     →  dict.keys()
    dict.viewkeys()
    dict.itervalues()  →  dict.values()
    dict.viewvalues()

 

  • xrange()    →  range()

 

  • cmp()    →  代替メソッドなし

 

  • unicode()    →  str()

 

  • iterator.next()    →  next()

 

  • contextlib.nested    →  削除

 

  • itertools
    itertools.izip()       →  zip()
    itertools.ifilter()    →  filter()
    itertools.imap()    →  map()

戻り値の変更

リストからイテレータ

 

  • dict
    dict.items()
    dict.keys()
    dict.values()
    * dictionary の場合はビューオブジェクトが返る
  • map()
  • range()
  • zip()

str 型と bytes 型

 

  • struct の s 書式型
  • subprocess.Popen
  • hmac

文字型に関連する変更は、この他に多数ありそうですが、個々にドキュメントで確認するしかなさそうです。

文字データ

Python 2 の文字列型の str 型は ascii ベースで、別に unicode 型があります。ユニコード文字列を扱うには ‘u’ プリフィックスを指定するか unicode() を使用します。’b’ プリフィックスや、bytes() もありますがバイト型はなく str 型となります。バイト配列として扱うには bytearray() があります。
Python 2 では異なるタイプの文字列データを連結してもエラーにならない等、型としては曖昧な部分があります。

Python 3 の文字列型の str 型はユニコードベースで、新たに bytes 型が導入されており str 型 と bytes 型は別クラスで実装されています。unicode 型と言うものはありません。データの連結やエンコード、デコードも型が合わなければエラーとなります。文字列を扱うメソッドの入出力情報も注意が必要です。
また str 型データのインデックス参照の結果は Python 3 では文字ではなく数字となります。

その他

  • 削除された print 文
    print 文は削除され、print() 関数のみとなりました。print は予約語からも外されました。
    関数であるため、print には括弧が必要です。
    print 文の後ろの式の部分は引数として渡します。

 

  • 除算の扱い
    ‘/’ の結果は Python2 では整数ですが、Python 3 では浮動小数点が返ります。
    整数を返して欲しい場合は ‘//’ を使用します。

 

  • BaseException.message 属性の削除
    代わりに BaseException.args attribute が使用できます。

ここまで Python 2 と Python 3 の移植に伴う主な違いについて解説しました。次回は、移植に使用できるユーティリティを紹介します。