27

私は新しい Python プロジェクトを開始したばかりです。理想的には、最初から Python 2 および 3 のサポートを提供し、開発のオーバーヘッドを最小限に抑えたいと考えています。私の質問は、まったく新しいプロジェクトでこれを行う最善の方法は何ですか?

インストール スクリプトの一部として 2to3 または 3to2 を実行するプロジェクトに出くわしました。これは非常に一般的な方法のようです。ただし、これを行うにはいくつかの異なる方法があるようです。Distributeにも出会いました。

多言語の Python 2/Python 3 コードを作成するオプションもあります。これは恐ろしい考えのように思えますが、私は最近、Python 2 として実行しているにもかかわらず、Python 3 のコードとしてより慣用的なコードを書く傾向があることに気付きました。ついにその日がやってきましたが、デュアルサポートを提供したり、少なくとも支援したりすることはあまりありません。

私が見たデュアル サポートを提供するプロジェクトのほとんどは、Python 3 サポートを遅れて追加したので、白紙の状態の利点がある新しいプロジェクトにより適したより良い方法があるかどうか特に興味があります。

ありがとう!

4

5 に答える 5

7

私の経験では、プロジェクトの種類によって異なります。

それがライブラリまたは非常に自己完結型のアプリケーションである場合、一般的な選択は、Python 3.x で廃止された構造を可能な限り回避して Python 2.7 で開発し、手動で修正する必要がある py2to3 によって残された穴を特定する自動テストに頼ることです。

一方、実際のアプリケーションでは、まだ py3k に移植されていないライブラリ (時には重要なもの) に常に出くわす準備をしておいてください。ほとんどの場合、ライブラリを Python 3 に移植する以外に選択肢がないため、余裕がある場合は移植してください。通常はできません。そのため、この種のプロジェクトでは Python 3 をサポートしていません (ただし、必要に応じて簡単に移植できるコードを書くのに苦労しています)。

Unicode の処理については、このPyCon 2012 ビデオが非常に有益であることがわかりました。アドバイスは Python 2.x と 3.x の両方に有効です: 外部から来るすべての文字列をバイトとして扱い、できるだけ早く Unicode に変換し、文字列をできるだけ遅くバイトに変換して出力します。日付/時刻の処理に関する別の非常に有益なビデオがあります。

[アップデート]

これは古い答えです。今日 (2019 年) の時点で、Python 2.x を使用してプロジェクトを開始する正当な理由はなく、古いプロジェクトを Python 3.7+ に移植して Python 2.x のサポートを放棄する説得力のある理由がいくつかあります

于 2012-07-07T06:02:09.397 に答える
5

私の経験では、次のようなライブラリを使用しないsix方が良いです。代わりに、Scott Griffiths のアプローチcompat.pyとは異なり、必要なコードだけを含むパッケージごとに 1 つ用意しています。また、古いバージョンの Python をサポートしようとする負担もあります。実際のところ、2.6 以下および 3.2 以下の Python がなくなったことを受け入れると、生活はずっと楽になります。2.7 には、Python 3 のプレフィックスのないバージョンとまったく同じように動作する s のメソッドなど、バックポートされた互換性機能があります。一方、Python 3.3 では、Unicode 文字列のプレフィックスが再びサポートされています。six.view*dictu

非常に実質的なパッケージであっても、compat.py他のコードを変更せずに動作させるモジュールは非常に短い場合があります。これは、同僚と私が 2/3 ポリグロットの作成を支援したパッケージの例です。pikaPika は、Unicode と 8 ビット文字列を相互に混ぜ合わせて内部をめちゃくちゃにしてしまったプロジェクトの 1 つですが、今では Python 3 の本番環境で 6 か月以上問題なく使用しています。


__future__その他の重要なことは、開発時に常に次の s を使用することです。

from __future__ import absolute_import, division, print_function

どちらのプラットフォームでもunicode_literals呼び出されるタイプである必要がある文字列がいくつかあるため、を使用しないことをお勧めします。を使用しないstr場合は、次のことができます。 unicode_literals

  • b'123'は 8 ビットの文字列リテラルです
  • '123'str両方のプラットフォームのタイプです
  • u'123'両方のプラットフォームで適切な Unicode テキストです

いずれにせよ、インストール/パッケージのビルド時に 2to3を実行しないでください。一部のパッケージは過去にそれを行っていました。pip installこれらのパッケージの実行には、Python 2 では数秒かかりましたが、Python 3 では 1 分近くかかりました。

于 2016-03-12T15:49:15.563 に答える
2

2または3のどちらか好きなフレーバーを選び、単体テストでその中で本当にうまく機能するようにします。次に、py2to3またはpy3to2を実行した後、これらのテストが機能することを確認します。コードの1つのバージョンを維持することをお勧めします。

于 2012-07-07T05:08:20.707 に答える
1

Python 2.5 以前のサポートが必要な場合は、通常、Distribute とその 2to3 統合を使用するのが最善の方法です。ただし、Python 2.6 以降のみをサポートする必要がある場合は、コードを変換せずに Python 2 および Python 3 で実行できるようにします。これを簡単にするために、 sixライブラリも使用します。

于 2012-07-08T20:17:18.030 に答える
1

私の個人的な経験では、正しく変換できないことが多い 2to3/3to2 スクリプトに依存するよりも、Python 2 と 3 の両方で変更されずに機能するコードを作成する方が簡単です。

私はバイト型で多くのことを行っており、2to3 はこれらを変換するのが難しいため、私の状況は珍しいかもしれませんが、1 つのコード ベースを持つことの便利さは、コードにいくつかのハックがあることの厄介さを上回ります。

具体的な例として、私のbitstringモジュールは Python 3 への初期の変換であり、同じコードが Python 2.6/2.7/3.x に使用されています。ソースは 4000 行を超えるコードであり、これは、さまざまなメジャー バージョンで動作させるために必要なビットです。

# For Python 2.x/ 3.x coexistence
# Yes this is very very hacky.
try:
    xrange
    for i in range(256):
        BYTE_REVERSAL_DICT[i] = chr(int("{0:08b}".format(i)[::-1], 2))
except NameError:
    for i in range(256):
        BYTE_REVERSAL_DICT[i] = bytes([int("{0:08b}".format(i)[::-1], 2)])
    from io import IOBase as file
    xrange = range
    basestring = str

OK、それはきれいではありませんが、コードの 99% を適切な Python 2 スタイルで記述でき、Python 3 でも同じコードのすべての単体テストに合格することを意味します。このルートは万人向けではありませんが、検討するオプション。

于 2012-07-07T18:19:12.287 に答える