通过Python子进程模块在shell中进行管道

时间:2012-05-01 22:53:29

标签: python shell subprocess pipe

所以我正在尝试查询给定计算机上的前3个CPU“密集”进程,我发现这个shell命令:ps -eo pcpu,pid,user,args | sort -k 1 -r | head -3

我想在Python脚本中使用这些数据,因此我需要能够通过subprocess模块捕获上述命令的输出。以下工作,但只返回一个巨大的字符串,因为我没有将它限制在前3:

psResult = subprocess.check_output(['ps', '-eo', 'pcpu,user,args'])

我不太确定这个subprocess.check_output是如何运作的......我尝试过一次微薄的尝试:

subprocess.check_output(['ps', '-eo', 'pcpu,user,args', '|', 'sort', '-k', '1', '-r', '|', 'head', '-3'])

这给了我一个错误:ps: illegal argument: |

如何在Python中使用管道|符号,或者使用其他方式进行排序,而不必对psResult = subprocess.check_output(['ps', '-eo', 'pcpu,user,args'])返回的巨大字符串进行大量解析?

谢谢! 问候, -kstruct

4 个答案:

答案 0 :(得分:11)

您可以传递shell=True参数来执行plain shell命令:

import subprocess
subprocess.check_output('ps -eo pcpu,pid,user,args | sort -k 1 -r | head -3',
                        shell=True)

或者,使用ps和Python的内置字符串函数的排序选项,如下所示:

raw = subprocess.check_output('ps -eo pcpu,pid,user,args --sort -pcpu')
first_three_lines = list(raw.split('\n'))[:3]

答案 1 :(得分:6)

其他一些人建议使用shell=True,如果您将可信输入传递给shell,this answer就可以了。但是,shell=True引入了一些不安全因素。为安全起见,docs建议如下:

output=`dmesg | grep hda`
# becomes
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]

答案 2 :(得分:1)

如果您使用它,它应该可以工作:

subprocess.check_output("ps -eo pcpu,pid,user,args | sort -k 1 -r | head -3", shell=True)

然后命令使用/bin/sh完全相同地运行,因此管道将起作用。

答案 3 :(得分:1)

为什么要使用外部命令?使用psutil

import psutil
def cpu_percentage(proc):
    try:
        return proc.get_cpu_percent()
    except psutil.AccessDenied:
        return float('-inf')

top3 = sorted(psutil.process_iter(), key=cpu_percentage, reverse=True)[:3]
for proc in top3:
    # do whatever