Learning Python - Mark Lutz [180]
C:\misc> c:\python30\python
>>> log = open('log.txt', 'w')
>>> print(1, 2, 3, file=log) # 2.6: print >> log, 1, 2, 3
>>> print(4, 5, 6, file=log)
>>> log.close()
>>> print(7, 8, 9) # 2.6: print 7, 8, 9
7 8 9
>>> print(open('log.txt').read())
1 2 3
4 5 6
These extended forms of print are also commonly used to print error messages to the standard error stream, available to your script as the preopened file object sys.stderr. You can either use its file write methods and format the output manually, or print with redirection syntax:
>>> import sys
>>> sys.stderr.write(('Bad!' * 8) + '\n')
Bad!Bad!Bad!Bad!Bad!Bad!Bad!Bad!
>>> print('Bad!' * 8, file=sys.stderr) # 2.6: print >> sys.stderr, 'Bad' * 8
Bad!Bad!Bad!Bad!Bad!Bad!Bad!Bad!
Now that you know all about print redirections, the equivalence between printing and file write methods should be fairly obvious. The following interaction prints both ways in 3.0, then redirects the output to an external file to verify that the same text is printed:
>>> X = 1; Y = 2
>>> print(X, Y) # Print: the easy way
1 2
>>> import sys # Print: the hard way
>>> sys.stdout.write(str(X) + ' ' + str(Y) + '\n')
1 2
4
>>> print(X, Y, file=open('temp1', 'w')) # Redirect text to file
>>> open('temp2', 'w').write(str(X) + ' ' + str(Y) + '\n') # Send to file manually
4
>>> print(open('temp1', 'rb').read()) # Binary mode for bytes
b'1 2\r\n'
>>> print(open('temp2', 'rb').read())
b'1 2\r\n'
As you can see, unless you happen to enjoy typing, print operations are usually the best option for displaying text. For another example of the equivalence between prints and file writes, watch for a 3.0 print function emulation example in Chapter 18; it uses this code pattern to provide a general 3.0 print function equivalent for use in Python 2.6.
Version-Neutral Printing
Finally, if you cannot restrict your work to Python 3.0 but still want your prints to be compatible with 3.0, you have some options. For one, you can code 2.6 print statements and let 3.0’s 2to3 conversion script translate them to 3.0 function calls automatically. See the Python 3.0 documentation for more details about this script; it attempts to translate 2.X code to run under 3.0.
Alternatively, you can code 3.0 print function calls in your 2.6 code, by enabling the function call variant with a statement like the following:
from __future__ import print_function
This statement changes 2.6 to support 3.0’s print functions exactly. This way, you can use 3.0 print features and won’t have to change your prints if you later migrate to 3.0.
Also keep in mind that simple prints, like those in the first row of Table 11-5, work in either version of Python—because any expression may be enclosed in parentheses, we can always pretend to be calling a 3.0 print function in 2.6 by adding outer parentheses. The only downside to this is that it makes a tuple out of your printed objects if there are more than one—they will print with extra enclosing parentheses. In 3.0, for example, any number of objects may be listed in the call’s parentheses:
C:\misc> c:\python30\python
>>> print('spam') # 3.0 print function call syntax
spam
>>> print('spam', 'ham', 'eggs') # These are mutiple argments
spam ham eggs
The first of these works the same in 2.6, but the second generates a tuple in the output:
C:\misc> c:\python26\python
>>> print('spam') # 2.6 print statement, enclosing parens
spam
>>> print('spam', 'ham', 'eggs') # This is really a tuple object!
('spam', 'ham', 'eggs')
To be truly portable, you can format the print string as a single object, using the string formatting expression or method call, or other string tools that we studied in Chapter 7:
>>> print('%s %s %s' % ('spam', 'ham', 'eggs'))
spam ham eggs
>>> print('{0} {1} {2}'.format('spam', 'ham', 'eggs'))