26.7. 2to3 - 自动Python 2到3代码翻译

2to3是一个Python程序,它读取Python 2.x源代码,并应用一系列修复器将其转换为有效的Python 3.x代码。标准库包含一组丰富的修复程序,它们将处理几乎所有的代码。2to3支持库lib2to3是一个灵活的和通用的库,所以可以编写自己的修复软件2to3。lib2to3也可以适用于需要自动编辑Python代码的自定义应用程序。

26.7.1. 使用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显式禁用修复程序。以下示例仅运行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标志。请注意,只有 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

用正确的方法替换已弃用的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

basestring转换为str

buffer

buffer转换为memoryview此修订器是可选的,因为memoryview API与buffer类似,但不完全相同。

callable

callable(x)转换为isinstance(x, collections.Callable),向collections,如果需要的话。注意callable(x)在Python 3.2中返回,所以如果你不打算支持Python 3.1,你可以禁用这个修复软件。

dict

修复字典迭代方法。dict.iteritems() is converted to dict.items(), dict.iterkeys() to dict.keys(), and dict.itervalues() to dict.values(). 同样,dict.viewitems()dict.viewkeys()dict.viewvalues()分别转换为dict.items()dict.keys()dict.values()It also wraps existing usages of dict.items(), dict.keys(), and dict.values() in a call to list.

except

Converts except X, T to except X as T.

exec

exec语句转换为exec()函数。

execfile

删除execfile()的使用。execfile()的参数包含在open()compile()exec()

exitfunc

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

filter

list调用中使用filter()使用。

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 and type(x) == SomeClass are converted to isinstance(x, SomeClass). ,而 1成为,而 此修复程序还尝试在适当的地方使用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))

itertools_imports

删除itertools.ifilter()itertools.izip()itertools.imap()的导入。导入itertools.ifilterfalse()也会更改为itertools.filterfalse()

itertools

itertools.ifilter()itertools.izip()itertools.imap()的用法更改为其内建等效项。itertools.ifilterfalse()更改为itertools.filterfalse()

long

long重命名为int

map

list调用中换行map()它还会更改映射(无, x)list(x)使用 future_builtins 导入 地图禁用此修复程序。

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)].

print

print语句转换为print()函数。

raise

转换提高 E, V提高 E V)提高 E, V, / t7>到提高 E(V).with_traceback(T)如果E是元组,则翻译将不正确,因为替换元组在3.0中已除去异常。

raw_input

raw_input()转换为input()

reduce

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

reload

reload()转换为imp.reload()

renames

sys.maxint更改为sys.maxsize

repr

repr()函数替换backtick repr。

set_literal

用set字面值替换set构造函数的使用。此修订包是可选的。

standarderror

StandardError重命名为Exception

sys_exc

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

throw

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

tuple_params

删除隐式元组参数分拆。此修订包插入临时变量。

types

修复因删除types模块中的某些成员而导致的代码。

unicode

unicode重命名为str

urllib

处理urlliburllib2的重命名为urllib包。

ws_comma

从逗号分隔的项目中删除多余的空格。此修订包是可选的。

xrange

xrange()重新命名为range()并用list包装现有range()

xreadlines

Changes for x in file.xreadlines() to for x in file.

zip

list调用中封装zip()使用。当出现 future_builtins import zip时,

26.7.3. lib2to3 - 2to3的库

源代码: Lib/lib2to3/

注意

lib2to3 API应被视为不稳定,并且将来可能会发生巨大变化。