2to3转换后如何修复打印((双括号))?

How to fix print((double parentheses)) after 2to3 conversion?

将我的项目迁移到 Python 3 (2to3-3.7 -w -f print *) 时,我观察到 lot 的(但不是全部)打印语句变成了 print( (...)),所以这些语句现在打印元组而不是执行预期的行为。我发现如果我使用 -p,我现在会处于一个更好的位置,因为 from __future__ import print_function 位于每个受影响模块的顶部。

我正在考虑尝试使用 sed 来解决这个问题,但在我开始尝试之前,我想我会看看以前是否有其他人处理过这个问题。是否有 2to3 功能来清理它?

使用版本控制(git)并且在前后立即提交(以及2to3创建的.bak文件),但我是不确定如何将我所做的更改与打印情况隔离开来。

尝试使用 -p 标记。请参阅最后一个注释 here

When the -p is passed, 2to3 treats print as a function instead of a statement. This is useful when from __future__ import print_function is being used. If this option is not given, the print fixer will surround print calls in an extra set of parentheses because it cannot differentiate between the print statement with parentheses (such as print ("a" + "b" + "c")) and a true function call.

您已经在打印元组了。如果你不是,那么你现在也不是。

为了说明,您的代码必须一直使用 print,就好像它是一个函数:

# Python 2
print(somestring)

翻译后变成

# Python 3
print((somestring))

那不是元组,那是只是一对括号。它会在任一版本上产生相同的输出。事实上,2to3 足够聪明,可以再次去掉内括号;写入的实际输出只是

# Python 3
print(somestring)

但是,如果您在 Python 2:

中使用了多个参数
# Python 2
print(arg1, arg2)

那么你已经在打印一个元组了,因为那真的是:

value_to_print = (arg1, arg2)
print value_to_print

因此只有在 Python 中保留该行为才是正确的 3. 如果您看到 2to3 工具使用 print((....)),那么它确定您已经在打印元组。

演示:

$ cat testprint.py
print('not a tuple')
print('two-value', 'tuple')
$ python2.7 testprint.py
not a tuple
('two-value', 'tuple')
$ 2to3 -w -f print testprint.py
RefactoringTool: Refactored testprint.py
--- testprint.py    (original)
+++ testprint.py    (refactored)
@@ -1,2 +1,2 @@
 print('not a tuple')
-print('two-value', 'tuple')
+print(('two-value', 'tuple'))
RefactoringTool: Files that were modified:
RefactoringTool: testprint.py
$ python3.7 testprint.py
not a tuple
('two-value', 'tuple')

请注意,这不同于在您的 Python 2 代码中使用 from __future__ import print_function 来禁用 print 语句,从而使代码调用内置的 print() 函数。 2to3 工具已经检测到这种情况,并将通过 print(...) 函数调用不变:

$ cat futureprint.py
from __future__ import print_function
print('not', 'a tuple')
$ python2.7 futureprint.py
not a tuple
$ 2to3 -w -f print futureprint.py
RefactoringTool: No files need to be modified.
$ python3.7 futureprint.py
not a tuple

您可以强制 2to3 假设您的所有文件都使用 from __future__ import print_function,无论如何,使用 -p / --print-function 命令行开关:

-p, --print-function  Modify the grammar so that print() is a function

但是,任何 deliberate print (tuple_element1, tuple_element2, ...) 打印语句都会被错误翻译为函数调用:

$ cat printtuple.py
print ('two-value', 'tuple')
$ python2.7 printtuple.py
('two-value', 'tuple')
$ 2to3 -w -f print -p printtuple.py
RefactoringTool: No files need to be modified.
$ python3.7 printtuple.py
two-value tuple

如果您的代码已经有 print() 函数,您可以使用 2to3 的 -x print 参数来跳过转换。

如果您的代码中混合使用打印语句和函数,则可以使用此选项。 2to3 不能很好地处理打印功能中的复杂内容,因此在带有正则表达式搜索和替换的编辑器中,您可以用 semi-manual 的方式清理这些内容。例如在 vscode 中,搜索字符串的示例是

print\(\((.*\.format.*)\)\)\n

替换为

print\(\)

调整其他案例的内容。