CPythonからJythonへの移行
質問
Javaコードとの統合を改善するために、CPythonからJythonにコード(約30K LOC)を移動することを検討しています。
移行に役立つチェックリストまたはガイドがありますか?誰かが似たようなことをした経験がありますか?
Jythonサイトを読むと、ほとんどの問題はあまりにもわかりにくいようです私。
次のことに気付きました:
- スレッドセーフは問題です
- Unicodeのサポートはまったく異なるようです。これは私にとっては問題かもしれません
- mysqldbは機能せず、zxJDBCに置き換える必要があります
他に何かありますか?
関連する質問: CPython、Jython、IronPythonで動作するpythonコードを記述するための戦略は何ですか
解決 3
私はこれを他の回答と経験から集めたウィキとして始めています。自由に編集したり追加したりできますが、壊れたもののリストではなく実用的なアドバイスに固執するようにしてください。 Jythonサイトの相違点の古いリストを次に示します。
リソース管理
Jythonは参照カウントを使用しないため、リソースはリリース時に解放されます ガベージコレクトされます。これは、同等の CPythonプログラム
-
open( 'file')。read()
は、ファイルを自動的に閉じません。with open( 'file')をfp
のイディオムとして使用する方が良い。 - __ del __メソッドは、すぐにではなく、Jythonコードで非常に遅く呼び出されます オブジェクトへの最後の参照が削除された後。
MySQL統合
mysqldb
はcモジュールであるため、jythonでは機能しません。代わりに、あなた
Jythonにバンドルされている com.ziclix.python.sql.zxJDBC
を使用する必要があります。
次のMySQLdbコードを置き換えます。
connection = MySQLdb.connect(host, user, passwd, db, use_unicode=True, chatset='utf8')
with:
url = "jdbc:mysql://%s/%s?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull" % (host, db)
connections = zxJDBC.connect(url, user, passwd, "com.mysql.jdbc.Driver")
また、すべての _mysql_exception
を zxJDBC
に置き換える必要があります。
最後に、クエリプレースホルダーを%s
から?
に置き換える必要があります。
ユニコード
- Jythonで不正なUnicode文字を表現することはできません。何かしようとしている
unichr(0xd800)
のような場合、例外が発生し、リテラルu '\ ud800'
コード内で大混乱を招くだけです。
不足しているもの
パフォーマンス
- ほとんどのワークロードでは、JythonはCPythonよりもはるかに遅くなります。レポートは 3〜50倍遅い速度。
コミュニティ
Jythonプロジェクトはまだ生きていますが、動きが速いわけではありません。の devメーリングリスト 月に約20件のメッセージがあり、開発者は約2人しかいないようです 最近コードをコミットしています。
他のヒント
まず、Jythonの実装は非常に優れていると言わざるを得ません。ほとんどのことは「機能する」だけです。
ここで私が遭遇したいくつかのことがあります:
-
もちろん、
-
Cモジュールは使用できません。
-
open( 'file')。read()は、ファイルを自動的に閉じません。これは、ガベージコレクターの違いに関係しています。これにより、開いているファイルが多すぎるという問題が発生する可能性があります。 " with open( 'file')as fp"を使用することをお勧めします。イディオム。
-
現在の作業ディレクトリの設定(os.setcwd()を使用)は、Pythonコードでは機能しますが、Javaコードでは機能しません。ファイル関連のすべてについて現在の作業ディレクトリをエミュレートしますが、Jythonに対してのみエミュレートできます。
-
XML解析は、外部DTDが利用可能な場合、その検証を試みます。これにより、パーサーがネットワークを介してDTDをダウンロードするため、XML処理コードが大幅に遅くなる可能性があります。 この問題を報告しましたが、今のところ修正されていません。
-
__ del __メソッドは、オブジェクトへの最後の参照が削除された直後ではなく、Jythonコードで非常に遅く呼び出されます。
古いリストの違いがありますが、最近のリストがあります使用できません。
これまでのところ、さらに2つの問題に気付きました。
- 文字列インターン「a」は「a」は保証されていません(CPythonでの単なる実装フロックです)。これは深刻な問題になる可能性があり、実際に移植したライブラリの1つ(Jinja2)にありました。ユニットテストは(いつものように)あなたの親友です!
Jython 2.5b0 (trunk:5540, Oct 31 2008, 13:55:41) >>> 'a' is 'a' True >>> s = 'a' >>> 'a' is s False >>> 'a' == s True >>> intern('a') is intern(s) True
CPythonでの同じセッション:
Python 2.5.2 (r252:60911, Oct 5 2008, 19:24:49) >>> 'a' is 'a' True >>> s = 'a' >>> 'a' is s True >>> 'a' == s True >>> intern('a') is intern(s) True
- os.spawn *関数は実装されていません。代わりにsubprocess.callを使用してください。 subprocess.callを使用した実装は簡単で、パッチを受け入れると確信しているので、本当に驚きました。
(私はあなたと同じようなことをしており、最近アプリを移植しています)
しばらく前にプロジェクトをCPythonからJythonに切り替えたとき、タイムクリティカルなセクションで最大50倍の速度低下を実現しました。そのため、私はCPythonにとどまりました。
ただし、現在のバージョンではこれが変更されている可能性があります。
JPype を調査することもできます。 Jythonと比較してどれだけ成熟しているかはわかりませんが、CPythonがJavaコードにアクセスできるようにする必要があります。
最近、私は私のグループの学校で教授のプロジェクトに取り組みました。早い段階で、プロジェクトをPythonで作成することが決定されました。間違いなくCPythonを使用する必要がありました。私たちはPythonでプログラムを作成し、すべての単体テストが最終的に機能しました。ほとんどの人はすでにPythonではなくJavaをコンピューターにインストールしているため、Jython jarとして展開することにしました。したがって、Javaの標準ライブラリに含まれているため、SwingでGUIを作成しました。
Jythonでプログラムを初めて実行したとき、すぐにクラッシュしました。たとえば、csv.readerの「.fieldnames」常にNoneのように見えました。したがって、この問題を回避するには、コードのいくつかの部分を変更する必要がありました。
コードの別のセクションもクラッシュしました。これはCPythonでうまく機能しました。 Jythonは、変数が割り当てられる前に変数を参照していると私を非難しました(これは私を夢中にさせ、実際にはそうではありませんでした)。これは1つの例です。 ActiveStateのコードレシピの外部ソート
さらに悪いことに、パフォーマンスはひどいものでした。基本的に、このコードはいくつかのCSVファイルを組み合わせており、そのうちの1つは約2 GBでした。 CPythonでは、8.5分で実行されました。 Jythonでは、25分で実行されました。
これらの問題は2.5.2rc2で発生しました(この投稿を書いている時点での最新版)。