.. _chap2to3: ========================================== \ :py:mod:`2to3`\ ツールの使い方 ========================================== :py:mod:`2to3`\ の概要 +++++++++++++++++++++++++++++++++++++++++++++++++ .. |2to3| replace:: :py:mod:`2to3` .. |fixer| replace:: https://docs.python.org/ja/3/library/2to3.html#fixers |2to3| はPythonと共にインストールされる **標準的なツール** で、 その名の通りPython2向けのソースコードを、Python3対応のソースコードに 変換してくれます。後に説明する :py:mod:`future` モジュールも類似の機能を持つています(:any:`future_module` 参照)。 \ |2to3|\ はpython2対応コードをpython3対応コードに 変換する際に必要な変更のほとんどに対応していますが、若干の手直しを 必要とする場合があります。 しかしながら、Python2向けソースコードを Python3対応にする為の最初の一歩としては必須のツールです。 :py:mod:`future` モジュールの futureize コマンドや Modernize コマンドも内部ではlib2to3の機能を使っています。 .. hint:: 参考URL :name: future モジュールについてのドキュメント(URL) `python-modernize `_ `Automatic conversion to Py2/3 `_ `How to port Python 2 Code to Python 3 `_ :py:mod:`2to3`\ の基本的な使い方 +++++++++++++++++++++++++++++++++++++++++++++++++ |2to3|\ が変更された文法のどれに対応しているかは、 .. code-block:: bash 2to3 -l を実行することで確認できます。 この文章作成時に実行したところ、52の変換項目(変換サブプログラムに対応している)が挙げられました。 [#]_ .. [#] 2to3-3.10でもこの数(52)は同じでした。 .. hlist:: :columns: 5 * apply * asserts * basestring * *buffer* * dict * except * exec * execfile * exitfunc * filter * funcattrs * future * getcwdu * has_key * *idioms* * import * imports * imports2 * input * intern * isinstance * itertools * itertools_imports * long * map * metaclass * methodattrs * ne * next * nonzero * numliterals * operator * paren * print * raise * raw_input * reduce * reload * renames * repr * *set_literal* * standarderror * sys_exc * throw * tuple_params * types * unicode * urllib * *ws_comma* * xrange * xreadlines * zip これらの変換項目は "``-f``"オプションや"``-x``"オプションを追加することで、明示的に変換項目に有効化/無効化を指定できます。 これらの変換項目のいくつか( *buffer*, *idioms*, *set_lieteral*, *ws_comma* )はオプショナルな変換項目となっており、通常は無効化されています。 これらの変換項目による結果は、厳密に等価なプログラムを与える訳では無いことから、オプショナルな変換項目となっているようです。 \ ``-f``\ を使って変換項目を指定すると、明示的に指定した変換項目だけが有効化されます。既定の変換項目に変換項目を追加するには、 .. code-block:: bash 2to3 -f all -f <変換項目名> . とします。 変換項目(変換プログラム) ------------------------- 上にあげた変換項目(apply,...) の内容は、例えば \ https://docs.python.org/ja/3/library/2to3.html#fixers\ に説明されています。 これらの変換プログラムのうち、 ``imports/imports2`` は ``python2`` から ``python3`` への移行時にモジュール名が変更されたモジュール(例えばTkinter -> tkinter)に対応してくれます。 importsでは、Tkinter, FileDialo, Tix, ttk などのTk関係のモジュール、dbmに関連したモジュール, xmlrpcサーバ関係のモジュール、 httplibやHTTPServerに関連したモジュールなどに対応しています。 また、imports2ではwhichdbm, anydbmの使用がdbmモジュールを使うように変更されます。 importsとimports2に分離されているのは、"単に技術的な制約のため" だそうです。 ``urllib`` については ``imports`` とは別に変換プログラム ``urllib``(fix_urllib.py)が用意されています。 ``idioms`` 変換プログラムは、"Python コードをより Python らしい書き方" にするいくつかの変形を行います。 objectの型\ :code:`type(obj)`\ とTypeオブジェクト\ :code:`T`\ との 比較を、可能なところでは、\ :code:`isInstance(obj,T)`\ に置き換える、 \ :code:`while 1:`\ を\ :code:`while True:`\ に置き換える、 可能な場所では\ :code:`sorted(EXPR)`\ を使う、等の変換を行います。 Tabとスペース ------------------ http://python3porting.com/differences.html#index-14 には次の記載があります。 In Python 2 a tab will be equal to eight spaces as indentation, so you can indent one line with a tab, and the next line with eight spaces. This is confusing if you are using an editor that expands tabs to another number than eight spaces. In Python 3 a tab is only equal to another tab. This means that each indentation level has to be consistent in its use of tabs and spaces. If you have a file where an indented block sometimes uses spaces and sometimes tabs, you will get the error TabError: inconsistent use of tabs and spaces in indentation. つまり、python2では 一つのブロック中で tabとspaceを混在しても、tabとspaceの関係( 1 tab = 8 spaces)を使ってブロック内 の各行の始まりが一致していれば問題はありませんでした。 一方python3 では、同じブロックの中では、tabとスペースの数と位置が一致している必要があります。 このため、同じブロック内でtabとスペースの数が異なる行があるスクリプトでは、python2では動作するけれど、python3では動作しないことになります。 TABと空白の混在はエディタなどの環境の違いによって、見かけ上の構造と Pythonインタプリタからみた構造が異なる場合があります。 これはpython2においても同様ですので、python2/python3にかかわらずTABと空白の混在は避けておくのが得策です。 ちなみに私自身はemacsのPython-modeを使いpythonプログラムを開発します。 此の環境では、キーボードからのTAB入力は複数の空白に置き換えてくれます。 デフォルトは4個の空白ですが、これを変更することも可能です(Preference で\ ``Python Indent Offset``\ を変更する)。 変更部分の確認 --------------------- |2to3|\ を出力を指定するオプションをつけずに実行することで、 |2to3|\ が加える変更をdiff形式の出力で確認できます。 .. code-block:: bash 2to3 *.py あるいは .. code-block:: bash 2to3 . で現在にディレクトリにあるpythonコードで必要な変換内容を確認します。 必要に応じて、``-f``あるいは``-x``オプションをつけて変更項目の有効化/無効化を試行して見ます。 新しいディレクトリにPytho3対応ソースコードを作成する。 ---------------------------------------------------------------------------------------------------- |2to3|\ には様々なオプションが用意されていますが、次のシェルコマンド .. code-block:: bash mkdir ../PY3 2to3 -W -n -o ../PY3 . を知っていれば、最低限の用は足りるでしょう。このコマンドは、 python2のソースコードのディレクトリに現在居るとして、 #. Python3用の作業ディレクトリ../PY3を作成し、(mkdir ../PY3) #. そのディレクトリに現在のディレクトリにある全てのPythonソースコードを\ |2to3|\ で必要な場合には、Python3向けに変換し、(|2to3|\ ) #. 変換の必要の無いファイルを含めて(-W -n) #. 新しいディレクトリ(../PY3)に書き出します。(-o ../PY3) #. ``-n`` オプションは、オリジナルのPython2向けコードをbackupとして作成しないことを指定しています。 ``-n`` オプションは ``-o`` オプション を使う際には必須となっています。 \ |2to3|\ コマンドの詳細は、 .. code-block:: bash 2to3 --help で確認できます。 mercurialなどを使って管理している場合 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ソースコードを mercurial などの管理ツールを使って 管理している場合には、ブランチなどの機能を使って、python3版の 開発を進めることが考えられます。 .. code-block:: bash mkdir PY3 cd PY3 hg clone . によって、現在のバージョンのコピーを作業ディレクトリ(PY3)に作成します。ここで、 .. code-block:: bash 2to3 -w -n . を実行すると、Python3への変更が必要なファイルだけが\ |2to3|\ によって変更されます。 変更前のファイルをバックアップとして残して置きたい場合には、 .. code-block:: bash 2to3 -w とします。もっとも、hgで管理しているのであれば、hg diffで見ることができるので、あまり必要な無いように思われます。 setup ツールとの連携 ------------------------- setuptoolsを使ったinstall scriptでは、``use_2to3`` オプション を設定することで、”setup.py intall"実行時に自動的に\ |2to3|\ を適用してからインストールすることができます。 後で見るように、|2to3|\ で自動変換したプログラムがpython3では意図した動作とならない場合があることから、その有用性はあまり無いのかもしれません。 setuptools のドキュメントでも .. epigraph:: Setuptools provides a facility to invoke 2to3 on the code as a part of the build process, by setting the keyword parameter use_2to3 to True, but the Setuptools project strongly recommends instead developing a unified codebase using six, future, or another compatibility library. -- setuptools 45.2.0 documentation となっています。一般的には、この記述にも触れられている :py:mod:`six` あるいは :py:mod:`future` などのモジュールを使うことが推奨されています。必要な変更の数が少ない場合には、有効な方法ですので、ダメもとで一度試して見るだけの価値は有りそうです。