2

Possible Duplicate:
Assignment Condition in Python While Loop

What's the equivalent of this:

while (line = p.stdout.readline()) != '':
    ...

in Python?

I don't like having to do this:

line = p.stdout.readline()
while line != '':
    sys.stdout.write(line)
    line = p.stdout.readline()

Although I've been using the latter for years... I suspect there is no alternative. I thought p.stdout supported iteration, like

for line in p.stdout:
    sys.stdout.write(line)

but unfortunately it doesn't, unlike the handle returned from open() for example.

Edit: Sorry, I was wrong, it does support it, the problem is that I can't get it out right away like I can with p.stdout.readline(). Adding sys.stdout.flush() doesn't seem to help, so it must be getting buffered inside p.stdout.

Community
  • 1
  • 1
dgrant
  • 1,417
  • 3
  • 16
  • 23
  • 1
    `for line in p.stdout:` doesn't make much sense. It's *output*. Why do you think you can read it? – S.Lott Feb 09 '12 at 19:16
  • 1
    duplicates: [here](http://stackoverflow.com/questions/7780998/assignment-condition-in-python-while-loop), [here](http://stackoverflow.com/questions/4161578/variable-assignment-in-expressions) and [here](http://stackoverflow.com/questions/6631128/assignment-in-while-loop-in-python) ... I just search python+assignment+while – juliomalegria Feb 09 '12 at 19:20
  • S.Lott: it's the stdout from another process. – dgrant Feb 10 '12 at 00:55
  • julio: thanks, but only one of those dupes was helpful and the answer I was looking for was down at the bottom with 0 votes – dgrant Feb 10 '12 at 00:56

1 Answers1

9

You can accomplish this using the built-in function iter() using the two-argument call method:

for line in iter(p.stdout.readline, ''):
    ...

Documentation for this:

iter(o[, sentinel])
...
If the second argument, sentinel, is given, then o must be a callable object. The iterator created in this case will call o with no arguments for each call to its next() method; if the value returned is equal to sentinel, StopIteration will be raised, otherwise the value will be returned.

One useful application of the second form of iter() is to read lines of a file until a certain line is reached. The following example reads a file until the readline() method returns an empty string:

with open('mydata.txt') as fp:
    for line in iter(fp.readline, ''):
        process_line(line)

edit: Based on your edit it looks like your actual problem is related to buffering. Based on the context I am guessing you are using subprocess.Popen() with stdout=subprocess.PIPE. Instead of using the file handle p.stdout directly you should be p.communicate() to read the output of your subprocess.

Andrew Clark
  • 202,379
  • 35
  • 273
  • 306
  • You're right. I'm using subprocess.Popen() with stdout=subprocess.PIPE. I've tried using p.communicate() but then I don't get the stdout from the process in real-time, I get it after the process has died. I've been told that pexpect is what I really should use, but I don't want to...I should be able to use subprocess, and it seems to work fine if I use readline(), which is what I've used in the past. – dgrant Feb 10 '12 at 00:58