'Popen'对象不是Iterable

时间:2015-10-15 18:29:01

标签: python linux list python-3.x subprocess

我试图通过subprocess命令将一些ID添加到列表中。以下是我的代码:

list1=[]
list2=[]
list1 = subprocess.Popen("pgrep -u root",stdout=subprocess.PIPE, shell = True)
for i in list1:
    file1 = open(os.path.join('/proc',i,'status')).readlines()
    for line in file1:
        if line.startswith("Mem: "):
             id = int(line.split()[5])
        if line.startswith("Cpu: "):
             toC = int(line.split()[8])
list2 = (id,toC)
for k in list2:
    self.text.insert(INSERT,k[0])
    self.text.insert(INSERT,k[1])

我得到的错误是:'Popen'object不可迭代。 我正在创建一个列表并将ID提取到列表中,然后对于列表中的每个ID,我试图获取mem和cpu信息。此信息再次输入另一个空列表(list2)。我正在迭代list2来显示这些信息。我哪里错了?

3 个答案:

答案 0 :(得分:4)

如果您需要通话结果,则需要communicate 子进程对象

proc = subprocess.Popen(['pgrep', '-u', 'root'], stdout=subprocess.PIPE)
text = proc.communicate()[0].decode('utf-8')

for i in text.splitlines():
    ...

Popen对象不是进程的输出,它是表示正在运行的子进程的对象。

如果可以,请避免使用shell=True,因为它被广泛认为是安全问题,而您在此处不需要它。

答案 1 :(得分:1)

对于这种情况(您只是阅读stdoutstdin / stderr未受影响),您可能不想要.communicate.run。处理它们生成的线条更容易,这些API不会做(它们会在返回之前将所有内容缓冲到内存中)。

要逐行处理输出,只需更改:

for i in list1:

为:

for i in list1.stdout:

此外,您在Python 3上遇到类型问题;要解决这个问题(并避免shell=True出现问题),请将Popen行更改为:

list1 = subprocess.Popen(['pgrep', '-u', 'root'], stdout=subprocess.PIPE, universal_newlines=True)

其中universal_newlines=Truelist1.stdout读取str,而不是bytes

答案 2 :(得分:0)

调用subprocess.Popen会产生Popen object。它没有给你一个列表,也没有给你一些你可以迭代的东西,因为Popen对象是不可迭代的。

使用同一个库中的更高级别函数将输出作为字符串更容易,然后解析它并相应地循环。在Python 3.5中,您只需拨打subprocess.run

即可
res = subprocess.run(["pgrep", "-u", "root"], stdout=subprocess.PIPE)

将为您提供一个CompletedProcess对象,您可以从中检查输出。

在Python 3.4或更早版本中,您可以使用check_output