2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Python2to3アップデート方法】2to3でPython2系コードを3系用に自動変換

Last updated at Posted at 2019-04-16

目次

概要

Python2系のコードを3系用に自動変換してくれるツールであり、Pythonに標準で同梱されているモジュールである2to3の使い方について説明する。

ただし、このツールで変更が必要な箇所全てを網羅できるわけではないので注意してください。

この記事を読む前に

コード変換ツールはいくつかあり、それぞれ特徴が異なる。
まずは自分の環境にどのツールが合うのか、以下の記事を読んで判断することをオススメする。

事前準備

まずは検証用に、2系では動くが3系では動かないコードを作成する。

ディレクトリ構成

以下の構成で作成する。

.
`-- project
    |-- base.py
    `-- libs
        |-- __init__.py
        |-- base.py
        `-- sample_class.py

検証用コード

以下のファイルを作成する。

project/base.py
# -*- coding:utf-8 -*-
import libs.sample_class as sc


if __name__ == '__main__':
    '''
    3系ではprint()にする必要がある
    '''
    print 'This is a sample.\n'
    sc.SampleClass().sample_method()
project/libs/sample_class.py
# -*- coding:utf-8 -*-
'''
2系ではproject/libs/base.pyがimportされる
3系ではproject/base.pyがimportされる
'''
import base
'''
3系ではconfigparser
'''
import ConfigParser


class SampleClass(base.Base):

    def sample_method(self):
        '''
        3系ではprint()にする必要がある
        '''
        print '[division]'
        '''
        # 計算結果
        - 2系 => 0
        - 3系 => 0.5
        '''
        print '1/2 = {}'.format(1/2)
        print '1//2 = {}'.format(1//2)
project/libs/base.py
# -*- coding:utf-8 -*-
from abc import ABCMeta, abstractmethod

class Base(object):
    '''
    3系ではAbstractの書き方が異なる
    '''
    __metaclass__ = ABCMeta

    @abstractmethod
    def sample_method(self):
        raise NotImplementedError()

project/libs/__init__.py
空で作成する。

実行結果

2系での実行結果

以下が出力される。

$ python project/base.py
This is a sample.

[division]
1/2 = 0
1//2 = 0

3系での実行結果

3系と互換性がない書き方なので、当然エラーとなる。

$ python project/base.py
Traceback (most recent call last):
  File "base.py", line 2, in <module>
    import libs.sample_class as sc
  File "/code/libs/sample_class.py", line 9
    print '[division]'
                     ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print('[division]')?

2to3でコードを変換

Installation

2to3を利用するためには以下のインストールが必要。

# CentOSの場合
$ yum install python-tools
# Ubuntuの場合
$ apt-get install 2to3

Usage

変更が必要な箇所をチェック

projectディレクトリに対して、2to3を実行すると、再帰的にチェックしてくれる。
この段階ではまだdry-runであり、コードの変換は行われない。

$ 2to3 project/
RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: set_literal
RefactoringTool: Skipping implicit fixer: ws_comma
RefactoringTool: Refactored project/base.py
--- project/base.py	(original)
+++ project/base.py	(refactored)
@@ -6,5 +6,5 @@
     '''
     3系ではprint()にする必要がある
     '''
-    print 'This is a sample.\n'
+    print('This is a sample.\n')
     sc.SampleClass().sample_method()
RefactoringTool: Refactored project/libs/base.py
--- project/libs/base.py	(original)
+++ project/libs/base.py	(refactored)
@@ -1,11 +1,10 @@
 # -*- coding:utf-8 -*-
 from abc import ABCMeta, abstractmethod

-class Base(object):
+class Base(object, metaclass=ABCMeta):
     '''
     3系ではAbstractの書き方が異なる
     '''
-    __metaclass__ = ABCMeta

     @abstractmethod
     def sample_method(self):
RefactoringTool: Refactored project/libs/sample_class.py
--- project/libs/sample_class.py	(original)
+++ project/libs/sample_class.py	(refactored)
@@ -4,11 +4,11 @@
 2系ではproject/libs/base.pyがimportされる
 3系ではproject/base.pyがimportされる
 '''
-import base
+from . import base
 '''
 3系ではconfigparser
 '''
-import ConfigParser
+import configparser


 class SampleClass(base.Base):
@@ -17,11 +17,11 @@
         '''
         3系ではprint()にする必要がある
         '''
-        print '[division]'
+        print('[division]')
         '''
         # 計算結果
         - 2系 => 0
         - 3系 => 0.5
         '''
-        print '1/2 = {}'.format(1/2)
-        print '1//2 = {}'.format(1//2)
+        print('1/2 = {}'.format(1/2))
+        print('1//2 = {}'.format(1//2))
RefactoringTool: Files that need to be modified:
RefactoringTool: project/base.py
RefactoringTool: project/libs/base.py
RefactoringTool: project/libs/sample_class.py

コードを自動変換

以下のコマンドで、実際にコードを書き換える。

-wオプションを付けることで、ファイルを上書きして書き換えてくれる。
実行すると、バックアップファイルも作成される。

$ 2to3 -w project/

--nobackupsオプションを付けると、バックアップファイルは作成されない。

$ 2to3 -w --nobackups project/

コード自動変換後の3系での実行結果

書き換えを行ったコードを3系で実行してみる。
エラーは起きなくなった。また、1/2の実行結果が0.5になった。

参考:Python2系と3系の違い - 割り算の少数点以下の扱いについて

$ python project/base.py
This is a sample.

[division]
1/2 = 0.5
1//2 = 0

最後に

冒頭でも書きましたが、このツールで変更が必要な箇所全てを網羅できるわけではないので、動作確認をしながら修正必要箇所を見つけていく、という作業は必要になります。

関連記事

参考

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?