'Popen' 对象不可迭代

'Popen' object not Iterable

我正在尝试通过 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”对象不可迭代。 我正在创建一个列表并将 ID 提取到列表中,然后对于列表中的每个 ID,我试图获取内存和 cpu 信息。此信息再次输入到另一个空列表(list2)中。我正在遍历 list2 以显示这些信息。我哪里错了?

如果您想要通话的结果,您需要 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,因为它被广泛认为是一个安全问题,您在这里不需要它。

调用 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

对于这种情况(您只阅读 stdoutstdin/stderr 未受影响),您可能不希望 .communicate.run。在生成行时更容易处理行,而那些 API 不会这样做(它们在 returning 之前将所有内容缓冲到内存中)。

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

for i in list1:

至:

for i in list1.stdout:

此外,Python3 上的类型有问题;要解决这个问题(并避免 shell=True 的问题)将 Popen 行更改为:

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

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