捕获运行无限循环的进程的stdout和stderr

时间:2018-07-02 09:52:55

标签: python

我想运行一个进程,该进程从python脚本运行无限循环(例如,启动数据库服务器),并捕获stdout和stderr。我尝试了此操作,但是p.communicate()从未返回,显然是因为该过程需要首先完成。

from subprocess import Popen, PIPE, STDOUT
cmd = "python infinite_loop.py"
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
print("the process is running")
stdout, stderr = p.communicate()
print(stdout)

我想以某种流形式获取输出。例如,我可能想将每100个字符保存到一个新的日志文件中。我该怎么办?

1 个答案:

答案 0 :(得分:1)

编辑:与您已经拥有的东西更接近,因为异步似乎对于单个协程来说就显得过分了:

import sys
from subprocess import Popen, PIPE, STDOUT

args = (sys.executable, '-u', 'test4.py')
cmd = ' '.join(args)
p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, universal_newlines=True)
print("the process is running")

for line in iter(p.stdout.readline,''):
    line = line.rstrip()
    print(line)

原始

我把东西放在一起。下面的示例使用asyncio.subprocess从子流程的输出中读取行,然后对其进行处理(在这种情况下,仅对它们进行print())。

子进程由args指定,在我的情况下,该子进程仅使用以下脚本(test4.py)以无缓冲模式运行另一个python实例:

import time
for _ in range(10):
    print(time.time(), flush=True)
    time.sleep(1)

我睡在for循环中,因此很明显,程序完成后,是单独进入一行还是全部进入一行。 (如果您不相信我,可以将for循环更改为while True:,这将永远不会结束)。

“主管”脚本为:

import asyncio.subprocess
import sys


async def get_lines(args):
    proc = await asyncio.create_subprocess_exec(*args, stdout=asyncio.subprocess.PIPE)

    while proc.returncode is None:
        data = await proc.stdout.readline()
        if not data: break
        line = data.decode('ascii').rstrip()
        # Handle line (somehow)
        print(line)


if sys.platform == "win32":
    loop = asyncio.ProactorEventLoop()
    asyncio.set_event_loop(loop)
else:
    loop = asyncio.get_event_loop()

args = (sys.executable, '-u', 'test4.py')
loop.run_until_complete(get_lines(args))
loop.close()

请注意,async def是Python 3.5 +,but you could use @asyncio.coroutine in 3.4