返回输出之前,Python子进程在后台运行


问题内容

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

perf stat -p <my_pid>

现在,我想在后台在Python代码中运行此代码,直到希望终止它的操作并输出命令输出为止。为了表明我的意思:

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

.. CODE TO DEBUG ..

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

现在,我想确定在“ print x”行要做什么以终止该过程并检查输出。任何想法/帮助表示赞赏。

欢呼和感谢,


问题答案:

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

sudo perf stat -- python test.py

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

  1. 终止perf并使其输出收集的性能统计信息,您需要向其发送SIGINT信号(尝试使用sudo perf stat -p mypidctrl-\将不打印任何内容,而ctrl-c将打印)
  2. 您需要捕获,stderr因为perf将其输出发送到stderr(至少在我的版本中)
  3. 您需要使用fork()一个进程发送SIGINT,而另一进程在进程终止时读取它的输出。如果没有fork,它将无法正常工作,因为在您执行SIGINT了该perf过程之后,您将无法再从stdin中读取该过程,因为该进程已经消失了,而当您从头stdin开始读取该文件时,直到perf被正确终止,您将无法获得任何输出。

这意味着您将最终获得此python程序:

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%的情况。它几乎对perf数据没有影响,唯一的影响是对“总运行时间”(*xx seconds time elapsed