我试图通过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来显示这些信息。我哪里错了?
答案 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)
对于这种情况(您只是阅读stdout
且stdin
/ 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=True
从list1.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
。