Python 2コードをPython 3に移植する方法

前書き

Pythonは1980年代後半に開発され、1991年に最初に公開されました。 英国のコメディグループMonty Pythonに触発された名前で、Pythonは命令型汎用ABCプログラミング言語の後継者として考案されました。 最初の反復では、Pythonにはすでに例外処理、functions、およびclasses with inheritanceが含まれていました。

このチュートリアルでは、コードをPython 2からPython 3に移行する際のベストプラクティスと考慮事項、および両方のバージョンと互換性のあるコードを維持する必要があるかどうかについて説明します。

バックグラウンド

Python 2は2000年に公開され、より透明で包括的な言語開発プロセスを示しています。 さらに多くのプログラム機能が含まれており、開発中に機能が追加されました。

Python 3はPythonの未来と見なされており、現在開発中の言語のバージョンです。 2008年後半にリリースされたPython 3は、本質的な設計上の欠陥に対処し、修正しました。 ただし、Python 2との後方互換性がないため、Python 3の採用は遅れています。

Python 2.7は、2.xリリースの最後として2010年に公開されました。 Python 2.7の背後にある意図は、Python 2.xユーザーがPython 3に機能を移植するのを容易にすることで、両者の間にある程度の互換性を提供することでした。

チュートリアル「https://www.digitalocean.com/community/tutorials/python-2-vs-python-3-practical-considerations-2[Python 2 vs Python 3:実用的な考慮事項]。」

Python 2.7から始める

Python 3に移行するか、Python 2とPython 3を同時にサポートするには、Python 2コードがPython 2.7と完全に互換性があることを確認する必要があります。

多くの開発者は既にPython 2.7コードのみを使用していますが、以前のバージョンでのみサポートされているものはすべてPython 2.7で適切に動作し、Python 2.7スタイルと一貫性があることを確認することが重要です。

コードがPython 2.7にあることを確認することは、Python 2の唯一のバージョンであり、まだメンテナンスされており、バグ修正を受けているため、特に重要です。 Python 2の以前のバージョンで作業している場合は、サポートされなくなり、バグ修正を受け取っていないコードで発生する問題を回避する必要があります。

さらに、プログラミングエラーを探すPylintパッケージなど、コードの移植を容易にする一部のツールは、2.7より前のバージョンのPythonではサポートされていません。

Python 2.7は現在もサポートおよび保守されていますが、最終的には廃止されることを忘れないでください。 PEP 373は、Python 2.7のリリーススケジュールの詳細を示しており、執筆時点では、日没日を2020としてマークしています。

テスト範囲

テストケースの作成は、Python 2をPython 3コードに移行するために行われる作業の重要な部分です。 Pythonの複数のバージョンを維持している場合は、テストスイートが全体的に適切にカバーされていることを確認して、各バージョンが引き続き期待どおりに動作することを確認する必要があります。

テストの一環として、インタラクティブなPythonケースをすべての関数、メソッド、クラス、モジュールのdocstringに追加し、組み込みのdoctest moduleを使用して、それらが図のように機能することを確認できます。

doctestと一緒に、coverage.py packageを使用して単体テストのカバレッジを追跡できます。 このツールはプログラムを監視し、コードのどの部分が実行されたか、どの部分が実行できたが実行されなかったかを記録します。 coverage.pyは、レポートをコマンドラインに出力したり、HTML出力を提供したりできます。 通常、テストの有効性を測定するために使用され、テストによって実行されるコードの部分とそうでない部分を示します。

100%のテストカバレッジを目指しているわけではないことに注意してください。混乱を招くコードや異常なコードをすべてカバーするようにします。 ベストプラクティスを実現するには、80%のカバレッジを目指してください。

Python 2とPython 3の違いについて学ぶ

Python 2とPython 3の違いについて学習することで、Python 3で利用可能な、または利用できる新しい機能を活用できるようになります。

「https://www.digitalocean.com/community/tutorials/python-2-vs-python-3-practical-considerations-2[Python2 vs Python 3]」に関するガイドでは、key differencesの一部について説明しています。 s 2つのバージョン間で、official Python documentationを確認して詳細を確認できます。

移植と移行を開始するとき、今すぐ実装できる構文の変更がいくつかあります。

print

The print Python2のステートメントがに変更されました print() Python3の関数。

Python 2 Python 3

print "Hello, World!"

print("Hello, World!")

exec

The exec Python 2のステートメントは、Python3で明示的なローカルとグローバルを許可する関数に変更されました。

Python 2 Python 3

exec code

exec(code)

exec code in globals

exec(code, globals)

exec code in (globals, locals)

exec(code, globals, locals)

/および//

Python 2は、 / operator、Python3が導入されました // フロア分割用。

Python 2 Python 3

5 / 2 = 2

5 / 2 = 2.5

5 // 2 = 2

Python 2でこれらの演算子を使用するには、__future__モジュールのimportdivisionを使用します。

from __future__ import division

division with integersの詳細をご覧ください。

raise

Python 3では、引数を使用して例外を発生させるには括弧が必要であり、stringsを例外として使用することはできません。

Python 2 Python 3

raise Exception, args

raise Exception

raise Exception(args)

raise Exception, args, traceback

raise Exception(args).with_traceback(traceback)

raise "Error"

raise Exception("Error")

except

Python 2では、複数の例外をリストすることは困難でしたが、Python3ではそれが変更されました。

ご了承ください as で明示的に使用されます except Python 3

Python 2 Python 3

except Exception, variable:

except AnException as variable:

except (OneException, TwoException) as variable:

def

Python 2では、関数はtupleslistsのようなシーケンスを取り込むことができます。 Python 3では、この解凍は削除されました。

Python 2 Python 3

def function(arg1, (x, y)):

def function(arg1, x_y): x, y = x_y

expr

Python2のバッククォート構文はもう存在しません。 Use repr() or str.format() Python 3。

Python 2 Python 3

+x = \`355/113\ + `

x = repr(355/113):

文字列のフォーマット

文字列のフォーマット構文がPython2からPython3に変更されました。

Python 2 Python 3

"%d %s" % (i, s)

"{} {}".format(i, s)

"%d/%d=%f" % (355, 113, 355/113)

"{:d}/{:d}={:f}".format(355, 113, 355/113)

class

述べる必要はありません object Python 3。

Python 2

class MyClass(object):
    pass

Python 3

class MyClass:
    pass

Python 3では、メタクラスは metaclass キーワード。

Python 2

class MyClass:
    __metaclass__ = MyMeta
class MyClass(MyBase):
    __metaclass__ = MyMeta

Python 3

class MyClass(metaclass=type):
    pass
class MyClass(MyBase, metaclass=MyMeta):
    pass

更新コード

Python 2との互換性を維持しながらコードをPython3に自動的に更新するために使用できる2つの主要なツールがあります:futuremodernize。 これらのツールはそれぞれ動作が多少異なります。futureはPython 3イディオムを作成するように機能し、ベストプラクティスはPython 2に存在しますが、modernizeはPythonsix moduleを使用するPythonのPython2 / 3サブセットを対象としています。 )s互換性を向上させます。

これらのツールを使用してコードの書き換えの詳細を処理すると、潜在的な問題とあいまいさを特定して修正するのに役立ちます。

ユニットテストスイート上でツールを実行して、コードを視覚的に検査および検証し、自動修正が正確であることを確認できます。 テストに合格すると、コードを変換できます。

ここから、特にchanges between Python 2 and 3 noted in the section aboveを対象として、手動で修正する必要があります。

futureを活用して、このimportステートメントを各Python2.7モジュールに追加することを検討する必要があります。

from __future__ import print_function, division, absolute_imports, unicode_literals

これにより書き換えも行われますが、Python 2のコードがPython 3の構文と一致するようになります。

最後に、pylint packageを使用して、コード内の他の潜在的な問題を特定できます。 このパッケージには、PEP 8 style guideルールや使用エラーなど、発生する可能性のある幅広い問題をカバーする何百もの個別のルールが含まれています。

自動移行に使用されるpylintとツールを混乱させる可能性のある構造がコードに含まれている場合があります。 これらの構造を単純化できない場合は、ユニットテストケースを使用する必要があります。

継続的インテグレーション

Pythonの複数のバージョンのコードを維持する場合は、開発中のコードで可能な限り頻繁に(手動ではなく)継続的な統合を通じてユニットテストスイートを実行および再実行することに注意する必要があります。 。

Python 2および3の互換性メンテナンスの一部としてsix packageを使用する場合は、テストに複数の環境を使用する必要があります。

使用を検討できる環境管理ツールの1つはtox packageです。これは、パッケージが異なるPythonバージョンでインストールされていることを確認し、各環境でテストを実行し、継続的インテグレーションサーバーのフロントエンドとして機能するためです。

結論

開発者とコミュニティの注目がPython 3に集中するにつれて、言語はより洗練され、プログラマーの進化するニーズに沿ったものになり、Python 2.7へのサポートが少なくなることに留意することが重要です。 Python 2とPython 3の両方のコードベースのバージョンを維持することにした場合、前のバージョンよりもバグ修正が少なくなるため、前者の方が困難になる可能性があります。

Porting chardet to Python 3などのケーススタディを含め、Python2をPython3に移植したプロジェクトを検討することは価値があります。