返回输出之前在后台运行的 Python 子进程 [英] Python subprocess running in background before returning output

查看:29
本文介绍了返回输出之前在后台运行的 Python 子进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些 Python 代码想用 perf 进行调试.为此,我想使用子流程.以下命令返回进程的指令相关信息,直到通过 Ctrl^C 退出命令.

I have some Python code that I want to debug with perf. For that purpose I want to use subprocess. The following command returns instruction-related information of a process until the command is exited via Ctrl^C.

perf stat -p <my_pid>

现在,我想在后台的 Python 代码中运行它,直到我希望能够终止它的操作并打印命令输出.表达我的意思:

Now, I want to run this inside a Python code in background, until some point where I want to be able to terminate its operation and print the commands output. To show what I mean:

x = subprocess.call(["perf","stat","-p",str(GetMyProcessID())])

.. CODE TO DEBUG ..

print x   # I want to terminate subprocess here and output 'x'

现在,我想确定在 'print x' 行执行什么操作以终止进程并检查输出.任何想法/帮助表示赞赏.

Now, I want to determine what to do at the line of 'print x' to terminate the process and check the output. Any idea/help is appreciated.

提前干杯和感谢,

推荐答案

首先:我建议不要在你的 python 进程中调用 perf (正如你在下面的任务的复杂性中看到的那样),但是而是从命令行使用:

First: I advise against calling perf from within your python process (as you see in the complexity of the task below), but instead use is from the command line:

sudo perf stat -- python test.py

如果您真的想在 python 中调用 perf,那么您将面临一些棘手的问题:

If you really want to call perf from within python then you'll face some tricky problems:

  1. 要终止 perf 并使其输出收集的性能统计信息,您需要向其发送 SIGINT 信号(使用 sudo perf stat -p mypid: ctrl- 什么都不打印,而 ctrl-c 会)
  2. 您需要在 perf 将其输出发送到 stderr 时捕获 stderr(至少在我的版本中)
  3. 您需要将 fork() 与一个发送 SIGINT 的进程一起使用,而另一个在进程终止时读取它的输出.如果没有分叉,它将无法工作,因为在您 SIGINT 编辑 perf 进程后,您无法再从 stdin 读取,因为该进程已经消失,并且当您从 stdin 首先,在 perf 正确终止之前,您不会得到任何输出.
  1. to terminate perf and make it output the gathered performance stats you need to send it the SIGINT signal (try it out with sudo perf stat -p mypid: ctrl- will print nothing whereas ctrl-c will)
  2. you need to capture stderr as perf sends its output to stderr (at least in my version)
  3. you need to use fork() with one process sending SIGINT and the other reading it's output while the process dies. Without forks it won't work because after you SIGINTed the perf process you cannot read from stdin any more as the process is already gone, and when you read from stdin first you won't get any output until perf is correctly terminated.

这意味着你最终会得到这个 python 程序:

That means you'd end up with this python program:

import subprocess
import os
import signal
import time

perf = subprocess.Popen(['perf', 'stat',  '-p', str(os.getpid())], stderr=subprocess.PIPE)

# <-- your code goes here

if os.fork() == 0:
    # child
    time.sleep(1)  # wait until parent runs `stderr.read()`
    perf.send_signal(signal.SIGINT)
    exit(0)

# parent
print("got perf stats>>{}<<".format(perf.stderr.read().decode("utf-8")))

time.sleep(1) 位是丑陋的,它会做什么,但我想它可以解决 99% 的情况.它对性能数据几乎没有影响,唯一的影响是对总运行时间"(*xx seconds time elapsed)

The time.sleep(1) bit is ugly, what it does it that it will but I guess it will do the trick for 99% of the cases. It has almost no influence on the perf data, the only influence it has is on the "total runtime" (*xx seconds time elapsed)

这篇关于返回输出之前在后台运行的 Python 子进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆