我试图从python脚本中捕获已执行命令的输出流。一切顺利,直到命令是python命令。
以下是我的函数,它们在stdout和stderr上获得具有不同回调的流:
capture_output.py
import sys
import logging
import shlex
import asyncio
async def _read_stream(stream, cb):
while True:
line = await stream.readline()
if line:
cb(line.decode())
else:
break
async def _stream_subprocess(cmd, stdout_cb, stderr_cb):
process = await asyncio.create_subprocess_exec(*cmd,
stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE)
await asyncio.wait([
_read_stream(process.stdout, stdout_cb),
_read_stream(process.stderr, stderr_cb)
])
return await process.wait()
def execute(cmd, stdout_cb, stderr_cb):
loop = asyncio.get_event_loop()
rc = loop.run_until_complete(
_stream_subprocess(
cmd,
stdout_cb,
stderr_cb,
))
loop.close()
return rc
def run_command(command,
output_function=lambda x: print("STDOUT: %s" % x),
error_handling=lambda x: print("STDERR: %s" % x),
cwd=None):
execute(shlex.split(command), output_function, error_handling, )
if __name__ == "__main__":
"Get the command on 1st position and run it"
command_str = sys.argv[1]
run_command(command_str)
以下是外部命令的示例:
anylongrunning_script.sh
#!/bin/bash
for i in {1..5}
do
echo "$i"
sleep 0.5
done
如果我运行python capture_output.py "sh anylongrunning_script.sh"
,我会看到直播,一切进展顺利。
但是如果运行像python capture_output.py "python anylongrunning_script.py"
这样的python命令:
anylongrunning_script.py
import time
for i in range(1, 6):
print(i)
time.sleep(0.5)
输出将在最后一个块中呈现。 你知道shell" echo"之间的区别是什么?和一个python" print"在这种情况下?
答案 0 :(得分:1)
通过使用-u
选项运行命令来禁用输出缓冲。试试python capture_output.py "python -u anylongrunning_script.py"
通过为子进程设置PYTHONUNBUFFERED
env变量,可以确保所有python进程都使用无缓冲模式。