【Python】Python2代码到Python3代码转换
几乎所有的Python 2程序都需要一些修改才能正常地运行在Python 3的环境下。为了简化这个转换过程,Python 3自带了一个叫做2to3的实用脚本(Utility Script),这个脚本会将你的Python 2程序源文件作为输入,然后自动将其转换到Python 3的形式。
本文介绍一下在windows 10 环境下如何使用这个工具:
1)首先要先安装好python3,可到官网下载https://www.python.org/
2)使用Windows 命令提示符(cmd)打开2to3.py 脚本所在位置,如下图:
C:\Users\Ben>cd /d C:\Python37\Tools\scripts

3)紧接着运行 2to3.py 脚本
C:\Python37\Tools\scripts>python3 2to3.py --help

可以看见在python 2to3.py 后面是需要参数的,我们输入--help 可以看到所需的参数信息。
4)2to3.py 脚本可以单独转换python2.x 代码 到python3,也可以按照目录批量的转换。下面分别举例说明一下:
A 按目录转换
假设我要转换的代码所在目录在:E:\ipv6-master
那么在CMD里面输入:
C:\Python37\Tools\scripts>python3 2to3.py -w D:\CODE\WORK_TEST\HAOTEST\
B 按指定代码转换
C:\Python37\Tools\scripts>python3 2to3.py -w D:\CODE\WORK_TEST\ShortCall\PC_Dev\xueyan_pc_dev\mix23\shortcall_testdev\Actions.py
已知问题:
1)当要转换的代码在C盘的路径下,转换会出问题。显示:拒绝访问。可能是权限问题。
参考:
1)https://docs.python.org/3.0/library/2to3.html
2)http://old.sebug.net/paper/books/dive-into-python3/porting-code-to-python-3-with-2to3.html
3)http://dipyzh.bitbucket.org/porting-code-to-python-3-with-2to3.html
---------------------
参考:https://blog.csdn.net/u012211419/article/details/51136232
--------------
补充:《2to3 - 自动将 Python 2 代码转为 Python 3 代码》
参考:https://docs.python.org/zh-cn/3.7/library/2to3.html
2to3 是一个 Python 程序,它可以用来读取 Python 2.x 版本的代码,并使用一系列的*修复器 fixer* 来将其转换为合法的 Python 3.x 代码。标准库中已经包含了丰富的修复器,这足以处理绝大多数代码。不过 2to3 的支持库 lib2to3 是一个很灵活通用的库,所以你也可以为 2to3 编写你自己的修复器。lib2to3 也可以用在那些需要自动处理 Python 代码的应用中。
使用 2to3
2to3 通常会作为脚本和 Python 解释器一起安装,你可以在 Python 根目录的 Tools/scripts 文件夹下找到它。
2to3 的基本调用参数是一个需要转换的文件或目录列表。对于目录,会递归地寻找其中的 Python 源码。
这里有一个 Python 2.x 的源码文件,example.py:
def greet(name):
print "Hello, {0}!".format(name)
print "What's your name?"
name = raw_input()
greet(name)
它可以在命令行中使用 2to3 转换成 Python 3.x 版本的代码:
$ 2to3 example.py
这个命令会打印出和源文件的区别。通过传入 -w 参数,2to3 也可以把需要的修改写回到原文件中(除非传入了 -n 参数,否则会为原始文件创建一个副本):
$ 2to3 -w example.py
在转换完成后,example.py 看起来像是这样:
def greet(name):
print("Hello, {0}!".format(name))
print("What's your name?")
name = input()
greet(name)
注释和缩进都会在转换过程中保持不变。
默认情况下,2to3 会执行 预定义修复器 的集合。使用 -l 参数可以列出所有可用的修复器。使用 -f 参数可以明确指定需要使用的修复器集合。而使用 -x 参数则可以明确指定不使用的修复器。下面的例子会只使用 imports 和 has_key 修复器运行:
$ 2to3 -f imports -f has_key example.py
这个命令会执行除了 apply 之外的所有修复器:
$ 2to3 -x apply example.py
有一些修复器是需要*显式指定*的,它们默认不会执行,必须在命令行中列出才会执行。比如下面的例子,除了默认的修复器以外,还会执行 idioms 修复器:
$ 2to3 -f all -f idioms example.py
注意这里使用 all 来启用所有默认的修复器。
有些情况下 2to3 会找到源码中有一些需要修改,但是无法自动处理的代码。在这种情况下,2to3 会在差异处下面打印一个警告信息。你应该定位到相应的代码并对其进行修改,以使其兼容 Python 3.x。
2to3 也可以重构 doctests。使用 -d 开启这个模式。需要注意*只有* doctests 会被重构。这种模式下不需要文件是合法的 Python 代码。举例来说,reST 文档中类似 doctests 的示例也可以使用这个选项进行重构。
-v 选项可以输出更多转换程序的详细信息。
由于某些 print 语句可被解读为函数调用或是语句,2to3 并不是总能读取包含 print 函数的文件。当 2to3 检测到存在 from __future__ import print_function 编译器指令时,会修改其内部语法将 print() 解读为函数。这一变动也可以使用 -p 选项手动开启。使用 -p 来为已经转换过 print 语句的代码运行修复器。
-o 或 --output-dir 选项可以指定将转换后的文件写入其他目录中。由于这种情况下不会覆写原始文件,所以创建副本文件毫无意义,因此也需要使用 -n 选项来禁用创建副本。
3.2.3 新版功能: 增加了 -o 选项。
-W 或 --write-unchanged-files 选项用来告诉 2to3 始终需要输出文件,即使没有任何改动。这在使用 -o 参数时十分有用,这样就可以将整个 Python 源码包完整地转换到另一个目录。这个选项隐含了 -w 选项,否则等于没有作用。
3.2.3 新版功能: 增加了 -W 选项。
--add-suffix 选项接受一个字符串,用来作为后缀附加在输出文件名后面的后面。由于写入的文件名与原始文件不同,所以没有必要创建副本,因此 -n 选项也是必要的。举个例子:
$ 2to3 -n -W --add-suffix=3 example.py
这样会把转换后的文件写入 example.py3 文件。
3.2.3 新版功能: 增加了 --add-suffix 选项。
将整个项目从一个目录转换到另一个目录可以用这样的命令:
$ 2to3 --output-dir=python3-version/mycode -W -n python2-version/mycode
修复器
转换代码的每一个步骤都封装在修复器中。可以使用 2to3 -l 来列出可用的修复器。之前已经提到,每个修复器都可以独立地打开或是关闭。下面会对各个修复器做更详细的描述。
apply-
移除对
apply()的使用,举例来说,apply(function, *args, **kwargs)会被转换成function(*args,**kwargs)。
asserts-
将已弃用的
unittest方法替换为正确的。Python 2.x Python 3.x failUnlessEqual(a, b)assertEqual(a, b)assertEquals(a, b)assertEqual(a, b)failIfEqual(a, b)assertNotEqual(a, b)assertNotEquals(a, b)assertNotEqual(a, b)failUnless(a)assertTrue(a)assert_(a)assertTrue(a)failIf(a)assertFalse(a)failUnlessRaises(exc, cal)assertRaises(exc, cal)failUnlessAlmostEqual(a, b)assertAlmostEqual(a, b)assertAlmostEquals(a, b)assertAlmostEqual(a, b)failIfAlmostEqual(a, b)assertNotAlmostEqual(a, b)assertNotAlmostEquals(a, b)assertNotAlmostEqual(a, b)
basestring-
将
basestring转换为str。
buffer-
将
buffer转换为memoryview。这个修复器是可选的,因为memoryviewAPI 和buffer很相似,但不完全一样。
dict-
修复字典迭代方法。
dict.iteritems()会转换成dict.items(),dict.iterkeys()会转换成dict.keys(),dict.itervalues()会转换成dict.values()。类似的,dict.viewitems(),dict.viewkeys()和dict.viewvalues()会分别转换成dict.items(),dict.keys()和dict.values()。另外也会将原有的dict.items(),dict.keys()和dict.values()方法调用用list包装一层。
except-
将
except X, T转换为except X as T。
exec-
将
exec语句转换为exec()函数调用。
exitfunc-
将对
sys.exitfunc的赋值改为使用atexit模块代替。
funcattrs-
修复已经重命名的函数属性。比如
my_function.func_closure会被转换为my_function.__closure__。
future-
移除
from __future__ import new_feature语句。
getcwdu-
将
os.getcwdu()重命名为os.getcwd()。
has_key-
将
dict.has_key(key)转换为key in dict。
idioms-
这是一个可选的修复器,会进行多种转换,将 Python 代码变成更加常见的写法。类似
type(x) is SomeClass和type(x) == SomeClass的类型对比会被转换成isinstance(x, SomeClass)。while 1转换成while True。这个修复器还会在合适的地方使用sorted()函数。举个例子,这样的代码块:L = list(some_iterable) L.sort()会被转换为:
L = sorted(some_iterable)
import-
检测 sibling imports,并将其转换成相对 import。
imports-
处理标准库模块的重命名。
imports2-
处理标准库中其他模块的重命名。这个修复器由于一些技术上的限制,因此和
imports拆分开了。
input-
将
input(prompt)转换为eval(input(prompt))。
intern-
将
intern()转换为sys.intern()。
isinstance-
修复
isinstance()函数第二个实参中重复的类型。举例来说,isinstance(x, (int, int))会转换为isinstance(x, int),isinstance(x, (int, float, int))会转换为isinstance(x, (int, float))。
itertools_imports-
移除
itertools.ifilter(),itertools.izip()以及itertools.imap()的 import。对itertools.ifilterfalse()的 import 也会替换成itertools.filterfalse()。
itertools-
修改
itertools.ifilter(),itertools.izip()和itertools.imap()的调用为对应的内建实现。itertools.ifilterfalse()会替换成itertools.filterfalse()。
long-
将
long重命名为int。
metaclass-
将老的元类语法(类体中的
__metaclass__ = Meta)替换为新的(class X(metaclass=Meta))。
methodattrs-
修复老的方法属性名。例如
meth.im_func会被转换为meth.__func__。
ne-
转换老的不等语法,将
<>转为!=。
next-
将迭代器的
next()方法调用转为next()函数。也会将next()方法重命名为__next__()。
nonzero-
将
__nonzero__()转换为__bool__()。
numliterals-
将八进制字面量转为新的语法。
operator-
将
operator模块中的许多方法调用转为其他的等效函数调用。如果有需要,会添加适当的import语句,比如import collections.abc。有以下转换映射:Python 2.x Python 3.x operator.isCallable(obj)callable(obj)operator.sequenceIncludes(obj)operator.contains(obj)operator.isSequenceType(obj)isinstance(obj, collections.abc.Sequence)operator.isMappingType(obj)isinstance(obj, collections.abc.Mapping)operator.isNumberType(obj)isinstance(obj, numbers.Number)operator.repeat(obj, n)operator.mul(obj, n)operator.irepeat(obj, n)operator.imul(obj, n)
paren-
在列表生成式中增加必须的括号。例如将
[x for x in 1, 2]转换为[x for x in (1, 2)]。
print-
将
print语句转换为print()函数。
raise-
将
raise E, V转换为raise E(V),将raise E, V, T转换为raise E(V).with_traceback(T)。如果E是元组,这样的转换是不正确的,因为用元组代替异常的做法在 3.0 中已经移除了。
raw_input-
将
raw_input()转换为input()。
reduce-
将
reduce()转换为functools.reduce()。
reload-
将
reload()转换为importlib.reload()。
renames-
将
sys.maxint转换为sys.maxsize。
repr-
将反引号 repr 表达式替换为
repr()函数。
set_literal-
将
set构造函数替换为 set literals 写法。这个修复器是可选的。
standarderror-
将
StandardError重命名为Exception。
sys_exc-
将弃用的
sys.exc_value,sys.exc_type,sys.exc_traceback替换为sys.exc_info()的用法。
throw-
修复生成器的
throw()方法的 API 变更。
tuple_params-
移除隐式的元组参数解包。这个修复器会插入临时变量。
types-
修复
type模块中一些成员的移除引起的代码问题。
unicode-
将
unicode重命名为str。
ws_comma-
移除逗号分隔的元素之间多余的空白。这个修复器是可选的。
xreadlines-
将
for x in file.xreadlines()转换为for x in file。
lib2to3 —— 2to3 支持库
源代码: Lib/lib2to3/
赠人玫瑰
手留余香
我们曾如此渴望命运的波澜,到最后才发现:人生最曼妙的风景,竟是内心的淡定与从容……我们曾如此期盼外界的认可,到最后才知道:世界是自己的,与他人毫无关系!-杨绛先生
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【关注我】。

浙公网安备 33010602011771号