I have a large chunk of code which uses the "print" statement. As to say in this way:
print "foo"
and not
print("foo")
I want to alter the output. Can I do this without changing all the lines with print? For example by overwriting the function/statement?
This changes the behavior of the print
statement without forcing you to change
print "foo"
to
print("foo")
import sys
_stdout = sys.stdout
class MyStream(object):
def __init__(self, target):
self.target = target
def write(self, s):
s = 'Foo : {!r}'.format(s)
self.target.write(s)
sys.stdout = MyStream(sys.stdout)
print 'Hi'
sys.stdout = _stdout # return print to its old behavior
yields
Foo : 'Hi'
This could be neatened with a context manager, but if you don't want to change your print
statements into print
functions, you probably don't want to have to wrap your print
statements in a context manager either.
So, a better, a more civilized way would be to use
2to3 --write --fix print test.py
to automatically change all the print
statements in your code (e.g. test.py above) into print
functions. Then you can change the behaviour by redefining the print
function:
from __future__ import print_function
import __builtin__
def print(*args, **kwargs):
__builtin__.print('Foo:', *args, **kwargs)
print('Hi')
yields
Foo: Hi
In Python 2, there is the print statement, which is a language construct. As such, you won’t be able to overwrite its behavior.
In Python 3, and in Python 2 if you enable it explicitely, you have the print function. It does require the parentheses, so print "foo"
will not work, but you can redefine what it does:
>>> from __future__ import print_function # for Python 2
>>> oldPrintFunction = print
>>> def print (*args, **kwargs):
oldPrintFunction('I am a changed print function')
oldPrintFunction(*args, **kwargs)
>>> print('foo')
I am a changed print function
foo
Python directly supports what you want to do:
from __future__ import print_function
Any module with that line at the top will treat the print
statement as a function instead, making the code compatible with both Python 2 and 3.
This applies just to the print
statement; you cannot override other statements.
This does mean you then have to use print()
as a function everywhere in that module, but you can then also provide your own implementation if you so desire:
from __future__ import print_function
import __builtin__
def print(*args, **kwargs):
__builtin__.print('Prefixed:', *args, **kwargs)
print('Hello world!')
Another option is to use a context manager to capture printed statements, directing the output away from sys.stdout
into a in-memory file object of your choosing:
from contextlib import contextmanager
import sys
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
@contextmanager
def capture_sys_output():
caputure_out = StringIO()
current_out = sys.stdout
try:
sys.stdout = caputure_out
yield caputure_out
finally:
sys.stdout = current_out
and wrap any blocks that you want to capture print
output for with the context manager. Here is an example prefixing printed lines:
with capture_sys_output as output:
print 'Hello world!'
output = output.get_value()
for line in output.splitlines():
print 'Prefixed:', line
or even provide a wrapper:
from contextlib import contextmanager
import sys
class Prefixer(object):
def __init__(self, prefix, orig):
self.prefix = prefix
self.orig = orig
def write(self, text):
self.orig.write(self.prefix + text)
def __getattr__(self, attr):
return getattr(self.orig, attr)
@contextmanager
def prefix_stdout(prefix):
current_out = sys.stdout
try:
sys.stdout = Prefixer(prefix, current_out)
yield
finally:
sys.stdout = current_out
and use as:
with prefix_stdout('Prefixed: '):
print 'Hello world!'
but take into account that print
statements usually write data to stdout
in separate chunks; the newline at the end is a separate write.
In Python 2.x, print
is a statement and so it can be called without parens. Apparently you're using that.
You can't overwrite the built-in print statement.
However, it writes its output to sys.stdout
. Perhaps you can overwrite sys.stdout with some object that has a .write method, like this:
import sys
from StringIO import StringIO
s = StringIO()
sys.stdout = s
print "Hmmm."
assert s.getvalue() == "Hmmm.\n"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With