diff --git a/pep-0214.txt b/pep-0214.txt new file mode 100644 index 000000000..c96174908 --- /dev/null +++ b/pep-0214.txt @@ -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: