Globally override built-in print function?

Lie Ryan lie.1296 at gmail.com
Fri Apr 16 04:14:26 EDT 2010


On 04/16/10 12:17, Dave W. wrote:
>>> I naively thought I could capture output from exec()'ed print
>>> invocations by (somehow) overriding 'print' globally.  But this
>>> seems not to be possible.  <snip>
> 
>>
>>    old_print = __builtins__.print
>>    __builtins__.print = printhook
>>    yield
>>    __builtins__.print = old_print
> 
> I'm pretty sure this is semantically equivalent to my original code,
> but I gave it a try anyway.  FWIW, it doesn't work, either. :-}
> 
>> But you really should replace sys.stdout and sys.stderr instead.
> 
> I'm starting to believe it, but... I thought that one of the
> benefits of making print a function was that it *could* be globally
> replaced. So far I've had no luck injecting a custom print
> replacement into other modules.  Is this really not possible?

No, the benefit of 'from __future__ import print_function' is for easing
transition to python 3. The ability to replace print globally only works
in python 3, after applying the change Robert Kern and turning raw_input
to input, the code works in python 3:

lieryan at compaq ~/junks $ python3 printhook.py
Python 3.1.2 (r312:79147, Apr 16 2010, 16:58:34)
[GCC 4.3.4]
linux2
Type "help", "copyright", "credits" or "license" for more info.
>>> print(32)
printhook(): 32

Note that assigning to __builtins__.print is different from assigning to
print. With the latter, you shadowed the print function in
__builtins__.print by putting your own print in the global namespace
(which in python really means module-level); while with the former
you're switching print in the interpreter level, the true global namespace.

========================================================
### File test.py ###
from __future__ import print_function
import sys
from code import InteractiveInterpreter
from contextlib import contextmanager

def printhook(*args):
    sys.stdout.write("printhook(): {0}\n".format(repr(args[0])))

@contextmanager
def global_printhook(printhook):
    global print
    print = printhook
    yield
    print = __builtins__.print

py = InteractiveInterpreter()

if not hasattr(sys, "ps1"): sys.ps1 = ">>> "
if not hasattr(sys, "ps2"): sys.ps2 = "... "

banner = ("Python %s\n%s\n" % (sys.version, sys.platform) +
          'Type "help", "copyright", "credits" or "license" '
          'for more info.\n')

sys.stdout.write(banner)
sys.stdout.write(sys.ps1)
while True:
    try:
        with global_printhook(printhook):
            result = py.runsource(input())
            if result is None:
                sys.stdout.write(sys.ps2)
            elif result is True:
                py.runcode(result)
    except EOFError:
        break
    else:
        sys.stdout.write(sys.ps1)
============================================================



More information about the Python-list mailing list