26.7. 2to3 - 自动Python 2到3代码翻译¶
2to3是一个Python程序,它读取Python 2.x源代码,并应用一系列修复器将其转换为有效的Python 3.x代码。标准库包含一组丰富的修复程序,它们将处理几乎所有的代码。2to3支持库lib2to3
是一个灵活的和通用的库,所以可以编写自己的修复软件2to3。lib2to3
也可以适用于需要自动编辑Python代码的自定义应用程序。
26.7.1. Using 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
将打印与原始源文件的差异。2to3也可以将需要的修改写回源文件。(除非提供-n
,否则将对原始文件进行备份。)使用-w
标志启用写回更改:
$ 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
显式禁用修复程序。以下示例仅运行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不能自动修复。在这种情况下,2to3将在文件的diff下面打印一个警告。您应该解决警告,以具有兼容的3.x代码。
2to3也可以重构doctests。要启用此模式,请使用-d
标志。请注意,只有 doctests将被重构。这也不需要模块是有效的Python。例如,doctest like reST文档中的示例也可以使用此选项重构。
-v
选项允许输出有关翻译过程的更多信息。
由于一些打印语句可以解析为函数调用或语句,因此2to3不能总是读取包含打印函数的文件。当2to3检测到来自 t> __未来__ 导入 print_function
编译器指令时,修改其内部语法以将print()
解释为函数。此更改也可以使用-p
标志手动启用。使用-p
在已经转换其打印语句的代码上运行修复程序。
-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
26.7.2. Fixers¶
转换代码的每个步骤都封装在修复程序中。命令2to3 -l
列出它们。由于documented above,每个可以单独打开和关闭。这里更详细地描述它们。
-
apply
¶ 删除
apply()
的使用。例如apply(function, * args, ** kwargs)
转换为函数(* args, ** kwargs)
。
-
asserts
¶ Replaces deprecated
unittest
method names with the correct ones.从 至 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)
-
buffer
¶ 将
buffer
转换为memoryview
。此修订器是可选的,因为memoryview
API与buffer
类似,但不完全相同。
-
callable
¶ Converts
callable(x)
toisinstance(x, collections.Callable)
, adding an import tocollections
if needed. 注意callable(x)
在Python 3.2中返回,所以如果你不打算支持Python 3.1,你可以禁用这个修复软件。
-
dict
¶ 修复字典迭代方法。
dict.iteritems()
is converted todict.items()
,dict.iterkeys()
todict.keys()
, anddict.itervalues()
todict.values()
. 同样,dict.viewitems()
,dict.viewkeys()
和dict.viewvalues()
分别转换为dict.items()
,dict.keys()
和dict.values()
。It also wraps existing usages ofdict.items()
,dict.keys()
, anddict.values()
in a call tolist
.
-
except
¶ Converts
except X, T
toexcept X as T
.
-
funcattrs
¶ 修复已重命名的函数属性。例如,
my_function.func_closure
将转换为my_function.__closure__
。
-
future
¶ 从 __未来__ 导入 new_feature语句中删除
-
getcwdu
¶ 将
os.getcwdu()
重命名为os.getcwd()
。
-
has_key
¶ 在 dict中将
dict.has_key(key)
更改为键 。
-
idioms
¶ 这个可选的修复程序执行几个转换,使Python代码更惯用。Type comparisons like
type(x) is SomeClass
andtype(x) == SomeClass
are converted toisinstance(x, SomeClass)
.,而 1
成为,而
此修复程序还尝试在适当的地方使用sorted()
。例如,这个块L = list(some_iterable) L.sort()
改为
L = sorted(some_iterable)
-
import
¶ 检测兄弟导入,并将其转换为相对导入。
-
imports
¶ 处理标准库中的模块重命名。
-
input
¶ 将
input(prompt)
转换为eval(input(prompt))
。
-
intern
¶ 将
intern()
转换为sys.intern()
。
-
isinstance
¶ 修复
isinstance()
的第二个参数中的重复类型。例如,isinstance(x, (int, int))
被转换为isinstance(x, (int))
。
-
itertools_imports
¶ 删除
itertools.ifilter()
,itertools.izip()
和itertools.imap()
的导入。导入itertools.ifilterfalse()
也会更改为itertools.filterfalse()
。
-
itertools
¶ 将
itertools.ifilter()
,itertools.izip()
和itertools.imap()
的用法更改为其内建等效项。itertools.ifilterfalse()
更改为itertools.filterfalse()
。
-
metaclass
¶ Converts the old metaclass syntax (
__metaclass__ = Meta
in the class body) to the new (class X(metaclass=Meta)
).
-
methodattrs
¶ 修复旧方法属性名称。例如,
meth.im_func
被转换为meth.__func__
。
-
ne
¶ 将旧的不等式语法
<>
转换为!=
。
-
next
¶ 将迭代器的
next()
方法转换为next()
函数。它还将next()
方法重命名为__next__()
。
-
nonzero
¶ 将
__nonzero__()
重命名为__bool__()
。
-
numliterals
¶ 将八进制字面值转换为新的语法。
-
operator
¶ 将对
operator
模块中各种函数的调用转换为其他函数,但等价的函数调用。需要时,添加适当的import
语句,例如import 容器
。进行以下映射:从 至 operator.isCallable(obj)
hasattr(obj, '__ call __')
operator.sequenceIncludes(obj)
operator.contains(obj)
operator.isSequenceType(obj)
isinstance(obj, 容器。序列)
operator.isMappingType(obj)
isinstance(obj, 容器.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
¶ 在列表推导式中添加需要的括号。For example,
[x for x in 1, 2]
becomes[x for x in (1, 2)]
.
-
raise
¶ 转换
提高 E, V
至提高 E V)
和提高 E, V, / t7>到
如果提高 E(V).with_traceback(T)
。E
是元组,则翻译将不正确,因为替换元组在3.0中已除去异常。
-
reduce
¶ 处理
reduce()
到functools.reduce()
的移动。
-
reload
¶ 将
reload()
转换为imp.reload()
。
-
renames
¶ 将
sys.maxint
更改为sys.maxsize
。
-
sys_exc
¶ 更改已弃用的
sys.exc_value
,sys.exc_type
,sys.exc_traceback
以使用sys.exc_info()
。
-
throw
¶ 修复生成器的
throw()
方法中的API更改。
-
tuple_params
¶ 删除隐式元组参数分拆。此修订包插入临时变量。
-
ws_comma
¶ 从逗号分隔的项目中删除多余的空格。此修订包是可选的。
-
xreadlines
¶ Changes
for x in file.xreadlines()
tofor x in file
.