从 Flask 视图流式传输 shell 输出有效,但永远不会结束
Streaming shell output from Flask view works, but never ends
我想将几个 python3 脚本的输出流式传输到我的浏览器。我遵循了来自不同 SO 答案的一些建议并且几乎解决了它。但是在执行脚本后,我从 stdout 读取的 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
returnsbytes
对象,而''
是一个str
对象,所以两者永远不会相等!
而是写
for line in iter(proc.stdout.readline, b''):
或者,甚至更好:
for line in proc.stdout:
我想将几个 python3 脚本的输出流式传输到我的浏览器。我遵循了来自不同 SO 答案的一些建议并且几乎解决了它。但是在执行脚本后,我从 stdout 读取的 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
returnsbytes
对象,而''
是一个str
对象,所以两者永远不会相等!
而是写
for line in iter(proc.stdout.readline, b''):
或者,甚至更好:
for line in proc.stdout: