Python 从函数打印生成

Python 从函数打印生成,python,python-3.x,flask,subprocess,generator,Python,Python 3.x,Flask,Subprocess,Generator,目前,我有一个调用另一个python文件的小flask项目。我完全意识到这种方式有点糟糕,因此,我想用它来交换函数调用,同时保持打印到网站上的图片 def get_Checks(): root = request.url_root def func(): yield ("Inicio <br>") with subprocess.Popen(r"python somefile.py", stdout=subprocess.PIPE,

目前,我有一个调用另一个python文件的小
flask
项目。我完全意识到这种方式有点糟糕,因此,我想用它来交换函数调用,同时保持打印到网站上的图片

def get_Checks():
    root = request.url_root

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

    return Response(func())
def get_Checks():
root=request.url\u root
def func():
收益率(“Inicio
”) 对于subprocess.Popen(r“python somefile.py”,stdout=subprocess.PIPE,bufsize=1, universal_newlines=True)作为p: 对于p.stdout中的行: 收益率(行+“
”) 返回响应(func())
我试图直接用函数替换文件调用,但它只是将其打印到控制台


非常感谢您提供的帮助。

假设您想要获取的所有打印都在同一个模块内完成,您可以对另一个模块的
打印功能进行修补。在下面的示例中,我使用上下文管理器在抓取完成后恢复原始打印功能

这是
mod1
,具有异常功能的模块

def bogus_function():
    print('Hello World!')
    print('Line 2')
这是使用
mod1.bogus_函数()的模块
mod2


一种简单的方法是临时将sys.stdout更改为类似文件的对象,调用函数,然后恢复sys.stdout
。输出将在类似文件的对象中可用

下面是一个演示该方法的工作烧瓶应用程序:

import sys
from io import StringIO
from flask import Flask, request, Response
import somefile

app = Flask(__name__)

@app.route("/")
def hello():
    def func():
        yield ("Inicio <br>")

        try:
            _stdout = sys.stdout
            sys.stdout = output = StringIO()
            somefile.main()
            output.seek(0)
            for line in output:
                sys.stdout = _stdout
                yield '{}<br>'.format(line.rstrip())
                sys.stdout = output
        finally:
            sys.stdout.close()    # close the StringIO object
            sys.stdout = _stdout  # restore sys.stdout

    return Response(func())

if __name__ == "__main__":
    app.run()

Damm,这比我预期的要复杂,但让我试试。它可以工作,但它会在每一行的末尾打印换行符(\n),任何方法都可以去掉它。(除了最后的替换)@EndermanAPM好的,我只添加了带有enumerate的打印循环来演示它的工作原理。@EndermanAPM要删除换行符,只需使用
line.rstrip('\r\n')
就可以了,没有enumerate,它的工作甚至比以前更好:)旧方法在某些字符的编码方面有一些问题:)这对我不起作用:它只是不在任何地方打印任何内容。@EnderNAPM:可能您正在交互式解释器中尝试这一点?如果是这种情况,那么玩弄
stdout
也会影响口译员的
stdout
。此代码旨在作为脚本执行,而不是以交互方式执行。它在Flask应用程序中绝对有效-请参阅更新的答案。@endermapm:BTW,有什么原因不能简单地更新
somefile.py
中的函数,让它产生这些行而不是打印它们?然后你可以把它称为生成器。不,我不是从交互式解释器运行的,我想我可以重写
somefile.py
。我添加到答案中的full Flask应用程序工作吗?(对我来说是这样)
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
import sys
from io import StringIO
from flask import Flask, request, Response
import somefile

app = Flask(__name__)

@app.route("/")
def hello():
    def func():
        yield ("Inicio <br>")

        try:
            _stdout = sys.stdout
            sys.stdout = output = StringIO()
            somefile.main()
            output.seek(0)
            for line in output:
                sys.stdout = _stdout
                yield '{}<br>'.format(line.rstrip())
                sys.stdout = output
        finally:
            sys.stdout.close()    # close the StringIO object
            sys.stdout = _stdout  # restore sys.stdout

    return Response(func())

if __name__ == "__main__":
    app.run()
def main():
    for i in range(10):
        print(i)

if __name__ == '__main__':
    main()