Assuming that all the printing you want to grab is done within the same module, You can monkey-patch the print
function of the other module. In the example below, I use a context manager to revert the original print function after the grabbing is done.
This is mod1
, the module with the misbehaving function.
def bogus_function():
print('Hello World!')
print('Line 2')
This is mod2
, the module using mod1.bogus_function()
import io
import functools
import contextlib
import mod1
@contextlib.contextmanager
def grab_stdout(module, fd):
def monkey_print(*args, **kwargs):
kwargs['file'] = fd
print(*args, **kwargs)
setattr(module, 'print', monkey_print)
try:
yield
finally:
setattr(module, 'print', print)
def line_generator():
fd = io.StringIO()
with grab_stdout(mod1, fd):
mod1.bogus_function()
fd.seek(0)
for line in fd:
yield line.rstrip('\r\n') + '<br>'
for t in enumerate(line_generator()):
print('line %d: %r' % t)
The grab_stdout()
context manager redirects print calls of module
to the file-like object fd
. In the function line_generator()
, grab_stdout()
is used to store the print output of bogus_function
in the StringIO
object fd
. The rest should be self-explanatory.
If you don't know exactly whether print is called in other modules in the call tree of the function in question, you can modify grab_stdout
as follows:
import builtins
print_orig = builtins.print
@contextlib.contextmanager
def grab_stdout_global(fd):
def monkey_print(*args, **kwargs):
kwargs['file'] = fd
print_orig(*args, **kwargs)
builtins.print = monkey_print
try:
yield
finally:
builtins.print = print_orig