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