154 lines
4.8 KiB
Plaintext
154 lines
4.8 KiB
Plaintext
PEP: 214
|
||
Title: Extended Print Statement
|
||
Version: $Revision$
|
||
Author: bwarsaw@beopen.com (Barry A. Warsaw)
|
||
Python-Version: 2.1
|
||
Status: Draft
|
||
Created: 24-Jul-2000
|
||
Post-History: 16-Aug-2000
|
||
|
||
|
||
Introduction
|
||
|
||
This PEP describes a syntax to extend the standard `print'
|
||
statement so that it can be used to print to any file-like object,
|
||
instead of the default sys.stdout. This PEP tracks the status and
|
||
ownership of this feature. It contains a description of the
|
||
feature and outlines changes necessary to support the feature.
|
||
This PEP summarizes discussions held in mailing list forums, and
|
||
provides URLs for further information, where appropriate. The CVS
|
||
revision history of this file contains the definitive historical
|
||
record.
|
||
|
||
|
||
Proposal
|
||
|
||
This proposal introduces a syntax extension to the print
|
||
statement, which allows the programmer to optionally specify the
|
||
output file target. An example usage is as follows:
|
||
|
||
print >> mylogfile, 'this message goes to my log file'
|
||
|
||
Formally, the syntax of the extended print statement is
|
||
|
||
print_stmt: ... | '>>' test [ (',' test)+ [','] ] )
|
||
|
||
where the ellipsis indicates the original print_stmt syntax
|
||
unchanged. In the extended form, the expression just after >>
|
||
must yield an object with a write() method (i.e. a file-like
|
||
object). Thus these two statements are equivalent:
|
||
|
||
print 'hello world'
|
||
print >> sys.stdout, 'hello world'
|
||
|
||
As are these two statements:
|
||
|
||
print
|
||
print >> sys.stdout
|
||
|
||
These two statements are syntax errors:
|
||
|
||
print ,
|
||
print >> sys.stdout,
|
||
|
||
|
||
Justification
|
||
|
||
`print' is a Python keyword and introduces the print statement as
|
||
described in section 6.6 of the language reference manual[1].
|
||
The print statement has a number of features:
|
||
|
||
- it auto-converts the items to strings
|
||
- it inserts spaces between items automatically
|
||
- it appends a newline unless the statement ends in a comma
|
||
|
||
The formatting that the print statement performs is limited; for
|
||
more control over the output, a combination of sys.stdout.write(),
|
||
and string interpolation can be used.
|
||
|
||
The print statement by definition outputs to sys.stdout. More
|
||
specifically, sys.stdout must be a file-like object with a write()
|
||
method, but it can be rebound to redirect output to files other
|
||
than specifically standard output. A typical idiom is
|
||
|
||
sys.stdout = mylogfile
|
||
try:
|
||
print 'this message goes to my log file'
|
||
finally:
|
||
sys.stdout = sys.__stdout__
|
||
|
||
The problem with this approach is that the binding is global, and
|
||
so affects every statement inside the try: clause. For example,
|
||
if we added a call to a function that actually did want to print
|
||
to stdout, this output too would get redirected to the logfile.
|
||
|
||
This approach is also very inconvenient for interleaving prints to
|
||
various output streams, and complicates coding in the face of
|
||
legitimate try/except or try/finally clauses.
|
||
|
||
|
||
Reference Implementation
|
||
|
||
A reference implementation, in the form of a patch against the
|
||
Python 2.0 source tree, is available on SourceForge's patch
|
||
manager[2]. This approach adds two new opcodes, PRINT_ITEM_TO and
|
||
PRINT_NEWLINE_TO, which simply pop the file like object off the
|
||
top of the stack and use it instead of sys.stdout as the output
|
||
stream.
|
||
|
||
|
||
Alternative Approaches
|
||
|
||
An alternative to this syntax change has been proposed (originally
|
||
by Moshe Zadka) which requires no syntax changes to Python. A
|
||
writeln() function could be provided (possibly as a builtin), that
|
||
would act much like extended print, with a few additional
|
||
features.
|
||
|
||
def writeln(*args, **kws):
|
||
import sys
|
||
file = sys.stdout
|
||
sep = ' '
|
||
end = '\n'
|
||
if kws.has_key('file'):
|
||
file = kws['file']
|
||
del kws['file']
|
||
if kws.has_key('nl'):
|
||
if not kws['nl']:
|
||
end = ' '
|
||
del kws['nl']
|
||
if kws.has_key('sep'):
|
||
sep = kws['sep']
|
||
del kws['sep']
|
||
if kws:
|
||
raise TypeError('unexpected keywords')
|
||
file.write(sep.join(map(str, args)) + end)
|
||
|
||
writeln() takes a three optional keyword arguments. In the
|
||
context of this proposal, the relevant argument is `file' which
|
||
can be set to a file-like object with a write() method. Thus
|
||
|
||
print >> mylogfile, 'this goes to my log file'
|
||
|
||
would be written as
|
||
|
||
writeln('this goes to my log file', file=mylogfile)
|
||
|
||
writeln() has the additional functionality that the keyword
|
||
argument `nl' is a flag specifying whether to append a newline or
|
||
not, and an argument `sep' which specifies the separator to output
|
||
in between each item.
|
||
|
||
|
||
References
|
||
|
||
[1] http://www.python.org/doc/current/ref/print.html
|
||
[2] http://sourceforge.net/patch/download.php?id=100970
|
||
|
||
|
||
|
||
Local Variables:
|
||
mode: indented-text
|
||
indent-tabs-mode: nil
|
||
End:
|