Reputation: 61
I am trying to fetch some Ids into a list via the subprocess command. Below is my code:
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])
The error that i get is: 'Popen'object not iterable. I am creating a list and fetching the IDs into a list and then for every ID in the list, I am trying to get the mem and cpu information. this information is again input into another empty list(list2). I am iterating over list2 to display these information. Where am I going wrong?
Upvotes: 1
Views: 11734
Reputation: 36822
If you want the result of the call you'll need to communicate with the subprocess object
proc = subprocess.Popen(['pgrep', '-u', 'root'], stdout=subprocess.PIPE)
text = proc.communicate()[0].decode('utf-8')
for i in text.splitlines():
...
The Popen
object is not the output of the process, it is an object that represents the running subprocess.
Also avoid shell=True
if you can as it is widely considered a security concern, and you don't need it here.
Upvotes: 6
Reputation: 155438
For this scenario (where you're only reading stdout
and stdin
/stderr
are untouched), you probably don't want .communicate
or .run
. It's easier to process the lines as they're produced, which those APIs don't do (they buffer everything into memory before returning).
To process the output line by line, just change:
for i in list1:
to:
for i in list1.stdout:
In addition, you've got a problem with types on Python 3; to fix that (and avoid the problems with shell=True
) change the Popen
line to:
list1 = subprocess.Popen(['pgrep', '-u', 'root'], stdout=subprocess.PIPE, universal_newlines=True)
where universal_newlines=True
makes reads from list1.stdout
return str
, not bytes
.
Upvotes: 1
Reputation: 26505
Calling subprocess.Popen
yields a Popen object. It does not give you a list and it does not give you something you can iterate over, because the Popen
object is not iterable.
It is easier to use a higher level function from the same library to get the output as a string, then parse this and loop accordingly. In Python 3.5, you can simply call subprocess.run
:
res = subprocess.run(["pgrep", "-u", "root"], stdout=subprocess.PIPE)
which will give you a CompletedProcess
object from where you can inspect the output.
In Python 3.4 or earlier, you can instead use check_output
.
Upvotes: 0