The right thing to do is to put make stdout a builtin and deprecate the
print statement. The "smart" behavior of the print statement causes more
trouble than it's worth. I admit that I use the print statement myself
occasionally, but only because 'sys.stdout.write' is too long to type all
the time, and never with more than one argument.
IMO, this is a job for bound methods...
import sys
stdwrite = sys.stdout.write
stdwriteln = sys.stdout.writelines
stdwriteln (["Hello ", "world\n"])
Of course, everyone wants something slightly different from their
default I/O stuff. One mans useful shortcut is another mans irritant
that he's constantly having to work around.
A simple formatting utility class is sometimes useful. After all,
formatting isn't just about where the spaces are. Word-wrapping,
indentation levels for paragraphs, bullet points and more can all make
life easy when generating complex console output. I even once
supported simple tables in a text mode output formatter, though not in
Python.
I just hacked the following together, if anyone is interested - it
definitely is not ready for real use, but it might be a useful start
for someone. The constructor optionally takes a callable object, used
to write each line, and a line length. The 'begin' and 'end' methods
do indented blocks, bullets etc. The main output methods are 'write',
'writeall' and 'writeln'.
'writeall' takes a single list parameter, converts every item in the
list using the 'str' function, and outputs each in turn.
'write' uses multiple parameters instead of a single list parameter.
'writeln' is like 'write', but ends the paragraph automatically. I'm
not sure where I got the 'ln' suffix from - either Pascal or Modula 2,
probably. Probably a bad name here, but what the hell.
'para' ends the current paragraph without writing more text.
'begin' normally takes a single string with the indent spaces and
possibly the bullet character. You might use " " for a simple indent,
for instance, or " * " for a bullet point. It can make an all-space
version for follow-on lines itself, but if you want something
different you can override it.
#
# Simple text-mode output formatter
#
import sys
import string
class Formatter :
target = sys.stdout.write
indent = ""
nxtindent = ""
curindent = None
indentstk = []
width = 80
pending = ""
separator = ""
terminator = "\n"
def __init__ (self,
target = sys.stdout.write,
width = 80 ) :
self.target = target
self.width = width
def begin (self, indent=" ", nxtindent=None) :
self.para ()
self.indentstk.append ((self.indent, self.nxtindent))
self.indent = self.nxtindent + indent
if nxtindent == None :
self.nxtindent += " " * len (indent)
else :
self.nxtindent += nxtindent
def end (self) :
self.para ()
self.indent = self.indentstk [-1] [0]
self.nxtindent = self.indentstk [-1] [1]
self.indentstk = self.indentstk [:-1]
def set_modifiers (self, separator = None, terminator = None) :
if separator != None :
self.separator = seperator
if terminator != None :
self.terminator = terminator
def write (self, *strings) :
self.writeall (strings)
def writeall (self, strings) :
t1 = string.join ([str (i) for i in strings], self.separator)
i = t1.find ("\n")
while i >= 0 :
self.pending += t1 [:i]
t1 = t1 [i+1:]
self.flush (True)
self.target ("\n")
i = t1.find ("\n")
self.pending += t1
self.flush (False)
def writeln (self, *strings) :
t1 = string.join ([str (i) for i in strings], self.separator) +
self.terminator
i = t1.find ("\n")
while i >= 0 :
self.pending += t1 [:i]
t1 = t1 [i+1:]
self.flush (True)
self.target ("\n")
i = t1.find ("\n")
self.pending += t1
self.flush (False)
def para (self) :
if self.pending != "" :
self.flush (True)
self.target ("\n")
def flush (self, force) :
if self.pending != "" :
if self.curindent == None :
self.curindent = self.indent
xwidth = self.width - len (self.indent)
while len(self.pending) >= xwidth :
i = xwidth - 1
while (i > 1) and (self.pending
!= ' ') :
i -= 1
self.target (self.curindent+string.rstrip (self.pending
[:i])+"\n")
self.curindent = self.nxtindent
self.pending=string.lstrip (self.pending [i:])
if force and (len (self.pending) > 0) :
self.target (self.curindent+string.rstrip (self.pending)+"\n")
self.curindent = None
self.pending=""