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]

  • 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を使って変換項目を指定すると、明示的に指定した変換項目だけが有効化されます。既定の変換項目に変換項目を追加するには、

2to3 -f all -f <変換項目名> .

とします。

3.2.1. 変換項目(変換プログラム)

上にあげた変換項目(apply,...) の内容は、例えば https://docs.python.org/ja/3/library/2to3.html#fixersに説明されています。

これらの変換プログラムのうち、 imports/imports2python2 から 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のソースコードのディレクトリに現在居るとして、

  1. Python3用の作業ディレクトリ../PY3を作成し、(mkdir ../PY3)

  2. そのディレクトリに現在のディレクトリにある全てのPythonソースコードを2to3で必要な場合には、Python3向けに変換し、(2to3)

  3. 変換の必要の無いファイルを含めて(-W -n)

  4. 新しいディレクトリ(../PY3)に書き出します。(-o ../PY3)

  5. -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 などのモジュールを使うことが推奨されています。必要な変更の数が少ない場合には、有効な方法ですので、ダメもとで一度試して見るだけの価値は有りそうです。