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

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

问题描述

我有一些要用perf调试的Python代码.为此,我想使用子过程.以下命令返回进程的指令相关信息,直到通过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. 您需要捕获stderr,因为perf将其输出发送到stderr(至少在我的版本中)
  3. 您需要使用fork(),其中一个进程发送SIGINT,而另一个进程在进程死亡时读取它的输出.如果没有分叉,它将不起作用,因为在SIGINT处理了perf进程后,由于该进程已经消失,您无法再从stdin读取数据,而当您从stdin进行读取时,直到得到该信息之前,您都不会得到任何输出性能已正确终止.
  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天全站免登陆