如何在进程仍在运行时收集进程输出(流数据)



我有一个在终端运行的服务(像Messenger一样),并且具有自己的印刷控制台,例如:

$ service-process --sync-start --text
> service started.
> wait to get results.
> TB1: 0X4571 
> TT1: 0X3321
..
..
..
> TY1: 0X6634
..
..
..
^Ctrl+C
exited
$

当我想获得输出时,我应该这样称呼:

$ service-process --sync-start --text >> output

将数据存储在文件中不是我情况的好解决方案。因此,我需要在我的python程序中获得它的打印输出,而此过程仍在其他终端(或背景)中运行。这个过程应该在服务器上运行很长时间。

我已经编写了此代码来收集输出(流数据),但是它从未收集所有这些代码,它只是收集一些第一个数据,并且很长一段时间永远不会工作(永远不要收集其他数据):

p = subprocess.Popen(['service-process', '--sync-start', '--text'], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
while True:
    output = ''
    if hasattr(p, 'stdout'):
        output = p.stdout.readline().strip().replace('n','').replace('r','')
    elif hasattr(p, 'stderr'):
        output = p.stderr.readline().strip().replace('n','').replace('r','')
    else:
        print('sleep...')
        time.sleep(1)
        continue
    print(output)

默认情况下,从 Popen.stdout&读取Popen.stderr将阻止,直到流中有数据为止。这可能会导致程序在stderr中等待数据的问题,而数据在stdout中可用,但是由于它被阻止了,因此无法参加stdout。我们可以使用fcntl(文件控制)Linux Syscall设置stdout&的文件描述符。 stderr to非阻滞。

这是一个示例代码:

import subprocess
from time import sleep
import fcntl, os
import sys
p = subprocess.Popen(['service-process', '--sync-start', '--text'], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
fcntl.fcntl(p.stderr.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
while True:
    out1 = ''
    out2 = ''
    if hasattr(p, 'stdout'):
        out1 = p.stdout.readline().strip().replace('n','').replace('r','')
    if hasattr(p, 'stderr'):
        out2 = p.stderr.readline().strip().replace('n','').replace('r','')
    if out1 != '':
        print(out1)
    if out2 != '':
        print(out2)
    sleep(1)

最新更新