从Flask视图流shell输出可以工作,但永远不会结束



我想将几个python3脚本的输出流式传输到我的浏览器。我从不同的SO答案中得到了一些建议,几乎解决了这个问题。但是,从标准输出读取的for循环在执行脚本后会进入无限循环。输出是正确的,一切都很好,但无尽的循环是一个问题。如何在输出完成后结束流?

@app.route('/stream/<script>')
def execute(script):
    def inner():
        assert re.match(r'^[a-zA-Z._-]+$', script)
        exec_path = "scripts/" + script + ".py"
        cmd = ["python3", "-u", exec_path]  # -u: don't buffer output
        proc = subprocess.Popen(
            cmd,
            stdout=subprocess.PIPE,
        )
        for line in iter(proc.stdout.readline, ''):
            yield highlight(line, BashLexer(), HtmlFormatter())
            # If process is done, break loop
   #         if proc.poll() == 0:
   #             break
    env = Environment(loader=FileSystemLoader('app/templates'))
    tmpl = env.get_template('stream.html')
    return Response(tmpl.generate(result=inner()))

当我轮询子进程以查看它是否已经完成时,脚本的输出中断了,因为当打印速度太快时,它没有打印整个标准输出流。如果我在每个打印之间添加一个sleep(1),问题就不会发生了。

代码可以工作,但是会进入一个无限循环。如果取消这些行的注释,输出将以某种方式被缓冲,部分输出将丢失。我还尝试在单独的线程中轮询子进程,只需要切换像if not running: break这样的标志,但这会导致与上面未注释代码相同的行为。

iter(proc.stdout.readline, '')调用readline,直到遇到等于''的东西。但是proc.stdout.readline返回bytes对象,而''str对象,所以两者永远不会相等!

可以写成

for line in iter(proc.stdout.readline, b''):

或者更好:

for line in proc.stdout:

相关内容

  • 没有找到相关文章

最新更新