3. 2to3ツールの使い方¶
3.1. 2to3の概要¶
2to3 はPythonと共にインストールされる 標準的なツール で、
その名の通りPython2向けのソースコードを、Python3対応のソースコードに
変換してくれます。後に説明する future モジュールも類似の機能を持つています(future モジュール 参照)。
2to3はpython2対応コードをpython3対応コードに
変換する際に必要な変更のほとんどに対応していますが、若干の手直しを
必要とする場合があります。
しかしながら、Python2向けソースコードを
Python3対応にする為の最初の一歩としては必須のツールです。
future モジュールの futureize コマンドや Modernize コマンドも内部ではlib2to3の機能を使っています。
3.2. 2to3の基本的な使い方¶
2to3 が変更された文法のどれに対応しているかは、
2to3 -l
を実行することで確認できます。 この文章作成時に実行したところ、52の変換項目(変換サブプログラムに対応している)が挙げられました。 [1]
|
|
|
|
|
これらの変換項目は "-f"オプションや"-x"オプションを追加することで、明示的に変換項目に有効化/無効化を指定できます。
これらの変換項目のいくつか( buffer, idioms, set_lieteral, ws_comma )はオプショナルな変換項目となっており、通常は無効化されています。
これらの変換項目による結果は、厳密に等価なプログラムを与える訳では無いことから、オプショナルな変換項目となっているようです。
-fを使って変換項目を指定すると、明示的に指定した変換項目だけが有効化されます。既定の変換項目に変換項目を追加するには、
2to3 -f all -f <変換項目名> .
とします。
3.2.1. 変換項目(変換プログラム)¶
上にあげた変換項目(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の型type(obj)とTypeオブジェクトTとの
比較を、可能なところでは、isInstance(obj,T)に置き換える、
while 1:をwhile True:に置き換える、
可能な場所ではsorted(EXPR)を使う、等の変換を行います。
3.2.2. 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を変更する)。
3.2.3. 変更部分の確認¶
2to3を出力を指定するオプションをつけずに実行することで、
2to3が加える変更をdiff形式の出力で確認できます。
2to3 *.py
あるいは
2to3 .
で現在にディレクトリにあるpythonコードで必要な変換内容を確認します。
必要に応じて、-f``あるいは-x``オプションをつけて変更項目の有効化/無効化を試行して見ます。
3.2.4. 新しいディレクトリにPytho3対応ソースコードを作成する。¶
2to3には様々なオプションが用意されていますが、次のシェルコマンド
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コマンドの詳細は、
2to3 --help
で確認できます。
3.3. mercurialなどを使って管理している場合¶
ソースコードを mercurial などの管理ツールを使って 管理している場合には、ブランチなどの機能を使って、python3版の 開発を進めることが考えられます。
mkdir PY3
cd PY3
hg clone <repository> .
によって、現在のバージョンのコピーを作業ディレクトリ(PY3)に作成します。ここで、
2to3 -w -n .
を実行すると、Python3への変更が必要なファイルだけが2to3によって変更されます。
変更前のファイルをバックアップとして残して置きたい場合には、
2to3 -w
とします。もっとも、hgで管理しているのであれば、hg diffで見ることができるので、あまり必要な無いように思われます。
3.3.1. setup ツールとの連携¶
setuptoolsを使ったinstall scriptでは、use_2to3 オプション
を設定することで、”setup.py intall"実行時に自動的に2to3を適用してからインストールすることができます。
後で見るように、2to3で自動変換したプログラムがpython3では意図した動作とならない場合があることから、その有用性はあまり無いのかもしれません。 setuptools のドキュメントでも
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
となっています。一般的には、この記述にも触れられている six あるいは future などのモジュールを使うことが推奨されています。必要な変更の数が少ない場合には、有効な方法ですので、ダメもとで一度試して見るだけの価値は有りそうです。