处理脚本内部的实时进程输出数据?

huangapple go评论75阅读模式
英文:

Handling live process output data inside of script?

问题

我正在尝试弄清楚如何在Python中处理进程的实时输出。我的队友给了我一个脚本,我们称之为applicationAPI.py,它执行以下操作:

  1. 建立与主机设备的TCP连接。
  2. 定义从主机设备上的应用程序中提取的多个度量标准。
  3. 实时将这些度量标准以CSV格式输出到我的标准输出(stdout),每60秒一次。

我试图做的是捕获来自这个进程的实时输出数据,并在我的Python脚本中解析它。我尝试使用以下代码:

import subprocess
import csv
from io import StringIO

api_call = subprocess.run(['./applicationAPI.py', '-target_ip', '-username', 
'-password', 'metric1', 'metric2', 'metric3', '-u', '60'], capture_output=True, text=True, check=True)

api_response = (api_call.stdout)
f = StringIO(api_response)
reader = csv.reader(f)
for line in reader:
    print(line)

但是它不起作用。问题在于这个进程是持续进行的。在60秒的时间间隔内,它将继续将数据输出到stdout。但它从不返回返回代码或完成执行。我尝试只是将输出重定向到文件,但同样,因为它是同一个进程,输出文件将永远不断增长。我不知道如何捕获或操作这些数据,以便在我的脚本中解析它。

英文:

I am trying to figure out how to handling live, ongoing, output of a process in python.
I was given a script from my teammates, lets call it applicationAPI.py, that does the following things:

  1. establish tcp connection to a host device
  2. defines a number of metrics to pull from the application on the host device
  3. outputs those metrics to my stdout in CSV format LIVE over a defined time interval, in this case every 60 seconds.

What I am trying to do is capture this live output data from this process, and parse it within my own python script. I tried to use subprocess with the following

import subprocess
import csv
import json

api_call = subprocess.run(['./applicationAPI.py', '-target_ip', '-username', 
'-password', 'metric1', 'metric2', 'metric3', '-u', '60'], capture_output=True, text=True, check=True)

api_response = (api_call.stdout)
f = StringIO(api_response)
reader = csv.reader(f)
for line in reader:
    print(line)

But it's not working. The problem is that the process is ongoing. For the 60 second time interval it will keep outputting data to stdout. But it never returns a return code or finishes executing. I tried to just redirect to a file, but again, because its the same process the output file would just grow and grow forever. I do not know how to capture or manipulate this data so I can parse it within my script.

答案1

得分: 0

你可以使用较低级别的 Popen 类,它提供了 stdoutstderr 管道以供读取。在启动进程时将 stderr 重定向到文件,然后从 stdout 中读取 csv 信息,直到进程完成。最后等待进程结束并读取返回代码。

import subprocess
import csv
import json
import tempfile

with tempfile.TemporaryFile() as stderr_file:

    api_call = subprocess.Popen(['./applicationAPI.py', '-target_ip', '-username',
        '-password', 'metric1', 'metric2', 'metric3', '-u', '60'],
        stdout=subprocess.PIPE, stderr=stderr_file)
    for row in csv.reader((line.decode() for line in api_call.stdout)):
        print(row)
    api_call.wait()
    if api_call.returncode != 0:
        stderr_file.seek(0)
        print(stderr_file.read())

这不是实时的。因为你使用的是管道,而不是终端,所以程序会缓冲 stdout。你只会在块大小边界处看到输出(也许每 2048 字节,但这取决于系统)。有时程序会包含一个标志,告诉它在每个换行符上刷新 stdout。也许这个程序有这样的标志,或者可以实现这个功能?

英文:

You could use the lower level Popen class which gives you stdout and stderr pipes to read. Redirect stderr ot a file when starting the process then read csv information from stdout until it completes. A final wait for the process to end and read the return code.

import subprocess
import csv
import json
import tempfile

with tempfile.TemporaryFile() as stderr_file:

    api_call = subprocess.Popen(['./applicationAPI.py', '-target_ip', '-username',
        '-password', 'metric1', 'metric2', 'metric3', '-u', '60'],
        stdout=subprocess.PIPE, stderr=stderr_file)
    for row in csv.reader((line.decode() for line in api_call.stdout)):
        print(row)
    api_call.wait()
    if api_call.returncode != 0:
        stderr_file.seek(0)
        print(stderr_file.read())

This isn't real time. Because you are using pipes, not a terminal, the program will buffer stdout. You'll only see output on block size boundaries (perhaps every 2048 bytes, but its system dependent). Sometimes programs include a flag that tells it to flush stdout on every newline. Perhaps this program has one or it could be implemented?

huangapple
  • 本文由 发表于 2023年6月26日 06:29:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76552647.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定