2015/03/25

Pythonの各実装(CPython/PyPy/Jython/IronPython)について

“Python” と言うとpython.orgが公開しているものを想像するが、これ以外にもPython言語で書かれたプログラムを動かすのに使えるソフトウェアは幾つか存在する。

それぞれの特性をよく知って、用途や目的に応じて使い分けるのがよい。

  1. 公式版 (CPython)
  2. PyPy
  3. Jython
  4. IronPython

公式版 (CPython)

  • 公式サイトは https://www.python.org/
  • Python言語で書かれたプログラムを動かすソフトウェアの “標準” として作られた実装で、"Python言語の仕様を表したソフトウェア" とも言える[1]
    • C言語で実装されているため、他実装との比較時に “CPython” と呼ばれるが、 “Cython” とは呼ばない[2]
    • 言語仕様や標準ライブラリ(標準付属モジュール群)の最新機能は他の実装よりも早い時期から利用できる
  • 実装の開発の上で(Python言語で書かれたコードの)動作速度には重点を置いていない
  • C言語による拡張モジュール(言語バインディング含む)はこの実装向けに作られる
    • こうしたC拡張モジュールの内部の処理はPython言語のみで書かれたものよりも高速に動作する
    • C拡張モジュールに依存したPythonプログラムは基本的にこの実装を用いて動かす必要がある
    • 幾つかの(主に処理速度が重要となる機能に関する)付属モジュール群はC言語で作成されている
  • GNU/Linuxでは基本的にディストリのパッケージとして利用可能で、Python 2系とPython 3系は別々のパッケージとしてインストール(共存)可だが、後者はpython3のようにコマンド名が異なることがある
  • スレッドの扱いに “GIL[3]という仕組みが用いられており、高負荷な処理を複数のスレッドで同時に実行してもCPU資源は活用されない

下はGILについての説明を引用したもの。

[引用] Pythonドキュメントの用語集ページの日本語訳 より
CPython インタプリタが利用している、一度に Python のバイトコード(bytecode) 実行するスレッドは一つだけであることを保証する仕組みです。これにより (dict などの重要な組み込み型を含む) などのオブジェクトモデルが暗黙的に同時アクセスに対して安全になるので、 CPython の実装がシンプルになります。インタプリタ全体をロックすることで、マルチプロセッサマシンが生じる並列化のコストに対して、楽にインタプリタをマルチスレッド化できます。ただし、標準あるいは外部のいくつかの拡張モジュールは、圧縮やハッシュ計算などの計算の重い処理をするときに GIL を解放するように設計されています。また、I/O 処理をするときも GIL は常に解放されます。

CPythonのスレッドも、入出力処理,一部モジュールの重い処理については効果はあり、CPU資源活用には “multiprocessing” パッケージによるマルチプロセス化が有効。

PyPy

  • 公式サイトは http://pypy.org/
  • JIT(Just-in-Time)コンパイラにより、 “Python言語で書かれた、処理量の多い、大規模なプログラム” では高速に動作する
    • RPython” という、Python言語に制約を加えた形の言語で実装されており、実行形式にビルドする際にもPyPyCPythonを用いる[4]
    • (メモリを多く使用するプログラムで特に)メモリ使用量を節約できる
    • 短時間で実行が終了するような小さなプログラムでは速度差は実感しにくい
    • CPython向けにビルドされたC拡張モジュールがそのままでは動かず[5]、専用の開発パッケージを用いてビルドする必要がある[6]
    • x86_32,x86_64,ARM以外のアーキテクチャでは利用できない(JITコンパイラのサポート状況による)
  • 2015年春時点ではPython 2.7系相当のバージョンと3.2系相当のバージョン(ベータ版扱い)がそれぞれ存在し、ディストリのパッケージとしては前者のみが用意されている場合もあるが、公式サイトで後者のGNU/Linux向けの実行ファイルを入手することもできる
  • バージョン系統は相当する公式版のバージョンとは別に付けられている
  • サンドボックス機能を持つ
  • 強化された並列処理機能を持つ “Stackless Python” と呼ばれる派生バージョン[7]の機能が利用できる
  • スレッドの扱いは “GIL” により本家版と同様

Jython

  • 公式サイトは http://www.jython.org/
  • Javaで実装されている
  • Javaクラスライブラリ(JCL)が利用できる
  • スレッド処理は真のマルチスレッドで動作
  • メモリ管理にJavaのガベージコレクション(GC)が使用される
  • Javaバイトコード(*.class)にスクリプト(*.py)をコンパイルできる[8]が、実行時には環境変数CLASSPATHの適切な指定が必要[9]
  • 新しいバージョンのPythonの仕様への対応が遅いが、将来的にはPython 3対応が予定されている
  • 動作も起動も遅い
Javaクラスライブラリの機能を用いた例
import java
java.lang.System.out.println ('Hello, Jython')
raise java.lang.NullPointerException

上の例の最後の行はJavaの例外をraise文で発生させる例で、深い意味はない。[10]

IronPython

  • 公式URLは https://ironpython.codeplex.com/
  • C#で実装されている
  • Mono/.NETの基本クラスライブラリ(BCL)が利用できる
  • Python 2.7系と互換のバージョン2.7系に加え、Python 3互換のバージョン(IronPython 3)も開発はされている
  • こちらもスレッド処理は真のマルチスレッドで動作
  • メモリ管理にMono/.NETのガベージコレクション(GC)が使用される
  • 動作も起動も遅い
  • Debian/Ubuntuでは過去にパッケージが存在していたが無くなっている(ソースからのビルドは可)
基本クラスライブラリの機能を用いた例
import System
System.Console.WriteLine ('Hello, IronPython')
[1]: いわゆる “リファレンス実装”
[2]: これは別のソフトウェアの名前として存在する
[3]: 通貨単位ではない
[4]: ただし変換処理には非常に時間とメモリが必要で、前者の実行ファイルを用いたほうがとても短時間で済むとされる
[5]: Luaの公式版に対するLuaJITとは異なり、CPythonとABI互換ではない
[6]: ビルドしても動作しない場合もあり、更にCPythonで使用した場合より低速とされる
[7]: 本家版をもとに修正を行った形の配布形式で、ディストリのパッケージになっていないことも多い
[8]: “compileall” モジュールを使用
[9]: Jythonと依存パッケージ群が動作に必要
[10]: …痛っ!!