英文:
Handling live process output data inside of script?
问题
我正在尝试弄清楚如何在Python中处理进程的实时输出。我的队友给了我一个脚本,我们称之为applicationAPI.py
,它执行以下操作:
- 建立与主机设备的TCP连接。
- 定义从主机设备上的应用程序中提取的多个度量标准。
- 实时将这些度量标准以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:
- establish tcp connection to a host device
- defines a number of metrics to pull from the application on the host device
- 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
类,它提供了 stdout
和 stderr
管道以供读取。在启动进程时将 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?
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论