Generator from function prints
<p>At the moment I have a little <code>flask</code> project that calls another python file. I'm fully aware that this way is kinda awful, and so, I want to swap it for a function call while maintaining <strong>the prints getting yelded to the website</strong>. </p>

<pre><code>def get_Checks():
    root = request.url_root

    def func():
        yield ("Inicio &lt;br&gt;")
        with subprocess.Popen(r"python somefile.py", stdout=subprocess.PIPE, bufsize=1,
                              universal_newlines=True) as p:
            for line in p.stdout:
                yield (line + "&lt;br&gt;")

    return Response(func())
</code></pre>

<p>I've tryed to replace the file call with the function directly but it just prints it to the console.</p>

<p>I really appreciate any help you can provide.</p>

<p>Assuming that all the printing you want to grab is done within the same module, You can monkey-patch the <code>print</code> 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.</p>

<p>This is <code>mod1</code>, the module with the misbehaving function.</p>

<pre><code>def bogus_function():
    print('Hello World!')
    print('Line 2')
</code></pre>

<p>This is <code>mod2</code>, the module using <code>mod1.bogus_function()</code></p>

<pre><code>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') + '&lt;br&gt;'

for t in enumerate(line_generator()):
    print('line %d: %r' % t)
</code></pre>

<p>The <code>grab_stdout()</code> context manager redirects print calls of <code>module</code> to the file-like object <code>fd</code>. In the function <code>line_generator()</code>, <code>grab_stdout()</code> is used to store the print output of <code>bogus_function</code> in the <code>StringIO</code> object <code>fd</code>. The rest should be self-explanatory.</p>

<p>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 <code>grab_stdout</code> as follows:</p>

<pre><code>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
</code></pre>

python python-3.x flask subprocess generator