Issue
When migrating my project to Python 3 (2to3-3.7 -w -f print *
), I observed that a lot of (but not all) print statements became print((...)), so these statements now print tuples instead of performing the expected behavior. I gather that if I'd used -p
, I'd be in a better place right now because from __future__ import print_function
is at the top of every affected module.
I'm thinking about trying to use sed to fix this, but before I break my teeth on that, I thought I'd see if anyone else has dealt with this before. Is there a 2to3 feature to clean this up?
I do use version control (git) and have commits immediately before and after (as well as the .bak files 2to3 creates), but I'm not sure how to isolate the changes I've made from the print situations.
Solution
You were already printing tuples. If you were not, then you are not now either.
To illustrate, your code would have to have been using print
as if it was a function:
# Python 2
print(somestring)
which becomes, after translation
# Python 3
print((somestring))
That's not a tuple, that's just a pair of parentheses. It results in the same output on either version. In fact, 2to3
is smart enough to drop the inner parentheses again; the actual output written is simply
# Python 3
print(somestring)
However, if you were using multiple arguments in Python 2:
# Python 2
print(arg1, arg2)
then you'd already be printing a tuple, because that's really:
value_to_print = (arg1, arg2)
print value_to_print
So it would only be correct to preserve that behaviour in Python 3. If you see the 2to3
tool use print((....))
, then it determined that you were already printing tuples.
Demo:
$ 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')
Note that this is different from using from __future__ import print_function
in your Python 2 code, to disable the print
statement and so making the code call the built-in print()
function. The 2to3 tool already detects this case and will pass through print(...)
function calls unchanged:
$ 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
You can force 2to3
to assume all your files use from __future__ import print_function
, regardless, with the -p
/ --print-function
command-line switch:
-p, --print-function Modify the grammar so that print() is a function
However, any deliberate print (tuple_element1, tuple_element2, ...)
print statements would then be mis-translated as function calls:
$ 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
Answered By - Martijn Pieters Answer Checked By - Marilyn (WPSolving Volunteer)