How to catch a line with Popen

Chris Torek nospam at torek.net
Sun May 29 21:02:41 EDT 2011


In article <irtj2o$h0m$1 at speranza.aioe.org>
TheSaint  <nobody at nowhere.net.no> wrote:
>Chris Rebert wrote:
>I just suppose to elaborate the latest line, as soon it's written on the 
>pipe, and print some result on the screen.
>Imaging something like
>
> p= Popen(['ping','-c40','www.google.com'], stdout=PIPE)
> for line in p.stdout:
>     print(str(line).split()[7])
>
>I'd like to see something like *time=54.4*
>This is just an example, where if we remove the "-c40" on the command line, 
>I'd expect to read the latest line(s), until the program will be killed.

In at least some versions of Python 2, file-like object "next"
iterators do not "work right" with unbuffered (or line-buffered)
pipe-file-objects.  (This may or may not be fixed in Python 3.)

A simple workaround is a little generator using readline():

def line_at_a_time(fileobj):
    """
    Return one line at a time from a file-like object.
    Works around the iter behavior of pipe files in
    Python 2.x, e.g., instead of "for line in file" you can
    write "for line in line_at_a_time(file)".
    """
    while True:
        line = fileobj.readline()
        if not line:
            return
        yield line

Adding this to your sample code gives something that works for me,
provided I fiddle with it to make sure that the only lines
examined are those with actual ping times:

    p = subprocess.Popen(["ping", "-c5", "www.google.com"],
        stdout = subprocess.PIPE)
    for lineno, line in enumerate(line_at_a_time(p.stdout)):
        if 1 <= lineno <= 5:
            print line.split()[6]
        else:
            print line.rstrip('\n')
    p.wait() # discard final result

(Presumably the enumerate() trick would not be needed in whatever
you really use.)
-- 
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W)  +1 801 277 2603
email: gmail (figure it out)      http://web.torek.net/torek/index.html



More information about the Python-list mailing list