2to 3-自动python 2到3代码转换

2to3是一个python程序,它读取python 2.x源代码并应用一系列 固定器 将其转换为有效的python 3.x代码。标准库包含一组丰富的修复程序,可以处理几乎所有代码。2to3支持库 lib2to3 不过,它是一个灵活的通用库,因此可以为2to3编写自己的修复程序。

使用2to3

2to3通常与python解释器一起作为脚本安装。它也位于 Tools/scripts python根目录。

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)

它可以通过命令行上的2to 3转换为python 3.x代码:

$ 2to3 example.py

将打印与原始源文件的差异。2to3还可以将所需的修改直接写回源文件。(备份原始文件,除非 -n 也给出。)使用 -w flag:

$ 2to3 -w example.py

改造后, example.py 如下所示:

def greet(name):
    print("Hello, {0}!".format(name))
print("What's your name?")
name = input()
greet(name)

在整个翻译过程中保留注释和精确的缩进。

默认情况下,2to3运行一组 predefined fixers . 这个 -l 标记列出所有可用的修复程序。可以使用 -f . 同样地 -x 显式禁用修复程序。以下示例仅运行 importshas_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无法自动修复。在这种情况下,2to3将在文件的diff下打印警告。为了使3.x代码符合要求,您应该处理警告。

2to3还可以重构doctests。要启用此模式,请使用 -d flag。注意 only 将重构doctest。这也不要求模块是有效的python。例如,REST文档中类似于doctest的示例也可以使用此选项进行重构。

这个 -v 选项允许输出有关翻译过程的更多信息。

由于某些print语句可以解析为函数调用或语句,因此2to3不能总是读取包含print函数的文件。当2to3检测到 from __future__ import print_function 编译器指令,它修改其内部语法以解释 print() 作为一种功能。也可以使用手动启用此更改 -p 标志。使用 -p 对已经转换了print语句的代码运行修复程序。阿尔索 -e 可用于制作 exec() 功能。

这个 -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 列出它们。AS documented above ,每个都可以单独打开和关闭。这里对它们进行了更详细的描述。

apply

删除的用法 apply() . 例如 apply(function, *args, **kwargs) 转换为 function(*args, **kwargs) .

asserts

替换已弃用的 unittest 方法名和正确的方法名。

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

皈依者 basestringstr .

buffer

皈依者 buffermemoryview . 此修复程序是可选的,因为 memoryview API类似,但与 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, Texcept X as T .

exec

转换 execexec() 功能。

execfile

删除的用法 execfile() .关于 execfile() 被封装在调用中 open()compile()exec() .

exitfunc

更改的分配 sys.exitfunc 使用 atexit 模块。

filter

包裹 filter() 在A中的用法 list 调用。

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 SomeClasstype(x) == SomeClass 转换为 isinstance(x, SomeClass) . while 1 变成 while True . 这个修理工也试图利用 sorted() 在适当的地方。例如,此块:

L = list(some_iterable)
L.sort()

更改为:

L = sorted(some_iterable)
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() . 输入 itertools.ifilterfalse() 也更改为 itertools.filterfalse() .

itertools

更改的用法 itertools.ifilter()itertools.izip()itertools.imap() 它们的内置等价物。 itertools.ifilterfalse() 已更改为 itertools.filterfalse() .

long

更名 longint .

map

包裹 map() 在一个 list 调用。它也改变了 map(None, x)list(x) . 使用 from future_builtins import map 禁用此修复程序。

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 . 进行以下映射:

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

转换 printprint() 功能。

raise

皈依者 raise E, Vraise E(V)raise E, V, Traise E(V).with_traceback(T) . 如果 E 是一个元组,转换将不正确,因为已在3.0中删除了用元组替换异常。

raw_input

皈依者 raw_input()input() .

reduce

处理的移动 reduce()functools.reduce() .

reload

皈依者 reload()importlib.reload() .

renames

变化 sys.maxintsys.maxsize .

repr

将Backtick Repr替换为 repr() 功能。

set_literal

取代了 set 带有设置文本的构造函数。此固定器是可选的。

standarderror

更名 StandardErrorException .

sys_exc

更改已弃用的 sys.exc_valuesys.exc_typesys.exc_traceback 使用 sys.exc_info() .

throw

修复生成器中的API更改 throw() 方法。

tuple_params

删除隐式元组参数解包。此修复程序插入临时变量。

types

修复从中删除某些成员时中断的代码 types 模块。

unicode

更名 unicodestr .

urllib

处理的重命名 urlliburllib2urllib 包裹。

ws_comma

从逗号分隔的项中删除多余的空白。此固定器是可选的。

xrange

更名 xrange()range() 并封装现有的 range() 调用 list .

xreadlines

变化 for x in file.xreadlines()for x in file .

zip

包裹 zip() 在A中的用法 list 调用。当 from future_builtins import zip 出现。

lib2to3 -2to3的库

源代码: Lib/lib2to3/


3.10 版后已移除: Python 3.9将切换到PEG解析器(请参见 PEP 617 ),Python 3.10可能包含lib2to3的LL(1)解析器无法解析的新语言语法。这个 lib2to3 模块可能会在将来的Python版本中从标准库中删除。考虑第三方替代方案,如 LibCSTparso .

注解

这个 lib2to3 API应被认为是不稳定的,并可能在未来发生剧烈变化。