简体   繁体   English

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

[英]Python subprocess running in background before returning output

I have some Python code that I want to debug with perf. 我有一些Python代码,我想用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. 以下命令返回进程的指令相关信息,直到通过Ctrl ^ C退出命令。

perf stat -p <my_pid>

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. 现在,我想在后台运行Python代码,直到我希望能够终止其操作并打印命令输出。 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'

Now, I want to determine what to do at the line of 'print x' to terminate the process and check the output. 现在,我想确定在'print x'行做什么来终止进程并检查输出。 Any idea/help is appreciated. 任何想法/帮助表示赞赏。

Cheers and thanks in advance, 提前干杯谢谢,

Use subprocess.Popen to run perf . 使用subprocess.Popen运行perf Then, use pipe.communicate() to send input and get the process's output. 然后,使用pipe.communicate()发送输入并获取进程的输出。

After you've done, call pipe.terminate() to terminate the process. 完成后,调用pipe.terminate()来终止进程。

For example: 例如:

pipe = subprocess.Popen(["perf","stat","-p",str(GetMyProcessID())], stdout=PIPE)

pipe.terminate()
stdout, stderr = pipe.communicate()
print stdout

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: 第一:我建议不要在你的python进程中调用perf (正如你在下面的任务的复杂性中看到的那样),而是使用来自命令行:

sudo perf stat -- python test.py

If you really want to call perf from within python then you'll face some tricky problems: 如果你真的想在python中调用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) 终止perf并使其输出,你需要给它发送收集到的性能统计SIGINT信号(尝试一下与sudo perf stat -p mypidctrl-\\将打印什么,而ctrl-c会)
  2. you need to capture stderr as perf sends its output to stderr (at least in my version) 你需要捕获stderr因为perf将其输出发送到stderr (至少在我的版本中)
  3. you need to use fork() with one process sending SIGINT and the other reading it's output while the process dies. 你需要使用fork() ,一个进程发送SIGINT ,另一个进程在进程SIGINT读取它的输出。 Without forks it won't work because after you SIGINT ed 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. 没有分支它将无法工作,因为在SIGINT ed perf过程之后,您无法再从stdin读取过程已经消失,并且当您从stdin读取时,您将无法获得任何输出,直到perf正确终止。

That means you'd end up with this python program: 这意味着你最终会得到这个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")))

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. time.sleep(1)位是丑陋的,它会做什么,但我想它会对99%的情况起作用。 It has almost no influence on the perf data, the only influence it has is on the "total runtime" ( *xx seconds time elapsed ) 它对perf数据几乎没有影响,它对“总运行时间”( *xx seconds time elapsed )的唯一影响

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM