2to3:将python2代码转为Python3代码

时间:2021-10-01 01:21:36


Python2的最后一个版本是2.7,在2020年彻底停止支持,但在网络上还能时不时地看到Python2的代码。这个时候就要用到 2to3将其转为python3的语法。

2to3是Python标准库中自带的一个脚本,可以读取Python2.x的源代码,并应用一系列修复程序将其转换为有效的Python 3.x代码。这个脚本通常会与Python解释器一起安装,位于当前环境Python路径的Tools/scripts目录中。

转换单个文件

如果只想转换一个名为ex.py的文件,你可以使用以下命令来查看转换后的代码:

2to3 ex.py

这个命令会在标准输出中打印出转换后的代码,并且会显示每一个修改点和对应的修复程序名称。

例如,如果ex.py文件内容如下:

print "Hello, world!"

则运行上面的命令后,你会看到类似以下的输出:

--- ex.py       (original)
+++ ex.py       (refactored)
@@ -1 +1 @@
-print "hello, world"
+print("hello, world")

其中-表示删除的原始代码,+表示添加的新代码。如果对转换后结果满意,则可使用-w选项来覆盖原始文件:

2to3 -w ex.py

然后ex.py这个文件就会被修改,而原始文件则会备份到example.py.bak中。如果在修改的过程中使用-n选项,则会禁止备份。

转换整个项目

如想转换一个项目,项目中包含多个文件或目录,则可以指定相应的目录列表作为参数:

2to3 proj_dir

这样会递归扫描proj_dir下所有以.py结尾的文件,并打印出所有修改点和对应修复程序名称。

和转换单文件相同的是,通过-w可以直接覆盖原始项目。

修复器

由于Python3与Python2.x在诸多模块处均有不同,所以2to3的修复过程也分门别类,通过指定不同的修复器,可以开启或关闭不同的修复规则。例如,

  • filterfilter()变为list(filter())
  • except将pyhton2.x中的except X, T转为except X as T,等等。
  • inputinput(prompt)转换为eval(input(prompt))
  • longlong重命名为int
  • next 将迭代器的next()方法转为next()函数。也会将next()方法重命名为__next__()
  • urlliburlliburllib2重命名为urllib包。
  • zip 用 list 包装 zip()。如果使用了 from future_builtins import zip 的话会禁用。
  • xrangexrange()重命名为range(),并用 list 包装原有的 range()。

还有相对复杂的可选修复器,例如

  • idioms 进行多种转换,将Python代码变成更加常见的写法。类似 type(x) is SomeClasstype(x) == SomeClass的类型对比会被转换成isinstance(x, SomeClass)while 1转换成while True,以及类似L = list(some_iterable).sort()改为L = sorted(some_iterable)等等。

由于内容很多,就不都贴在这里了。而最关键的改动print xxx转为print(xxx),则通过-p来调控。

使用2to3 -x xxx可以禁用xxx修复器;通过2to3 -f xxx则表示仅使用xxx修复器。

通过2to3 -l可以列举所有修复器。而除了2to3内置的修复程序之外,还可以编写自己的修复程序,并通过通过lib2to3.fixer_base中的BaseFix来自定义修复方法。但lib2to3已经被标为过时,并且马上就要弃用了,所以就不讲了。