PEP 214, Extended Print Statement, owned by bwarsaw
This commit is contained in:
parent
e025e06bbe
commit
041efa077b
|
@ -0,0 +1,153 @@
|
|||
PEP: 214
|
||||
Title: Extended Print Statement
|
||||
Version: $Revision$
|
||||
Owner: bwarsaw@beopen.com (Barry A. Warsaw)
|
||||
Python-Version: 2.0
|
||||
Status: Draft
|
||||
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
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
|
||||
|
||||
oldstdout = sys.stdout
|
||||
sys.stdout = mylogfile
|
||||
try:
|
||||
print 'this message goes to my log file'
|
||||
finally:
|
||||
sys.stdout = oldstdout
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
Proposal
|
||||
|
||||
This proposal introduces a syntax change 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: "print" [">>" expr ","] [ expr ("," expr)* [","] ]
|
||||
|
||||
Where the 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'
|
||||
|
||||
|
||||
|
||||
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]. The approach this patch takes is to introduce two new
|
||||
opcodes, one which temporarily rebinds sys.stdout to the specified
|
||||
file object, performs the print as normal, and then bind
|
||||
sys.stdout back to sys.__stdout__ (which is the real physical
|
||||
standard out and should not be changed). In some ways this is
|
||||
equivalent to the try/finally idiom above, except that the
|
||||
rebinding of sys.stdout is in effect only for the duration of the
|
||||
print statement itself.
|
||||
|
||||
An alternative approach is possible, where only one new opcode is
|
||||
added. This opcode would be exactly like the existing PRINT_ITEM
|
||||
opcode except that it would find the target file object at the top
|
||||
of the stack, and use this file instead of digging it out of
|
||||
sys.stdout.
|
||||
|
||||
|
||||
|
||||
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:
|
Loading…
Reference in New Issue