Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #6602

Re: How to catch a line with Popen

From Chris Torek <nospam@torek.net>
Newsgroups comp.lang.python
Subject Re: How to catch a line with Popen
Date 2011-05-30 01:02 +0000
Organization None of the Above
Message-ID <iruqbh0cdd@news3.newsguy.com> (permalink)
References <irr69j$6c1$1@speranza.aioe.org> <irt5k2$h7v$1@speranza.aioe.org> <mailman.2219.1306664812.9059.python-list@python.org> <irtj2o$h0m$1@speranza.aioe.org>

Show all headers | View raw


In article <irtj2o$h0m$1@speranza.aioe.org>
TheSaint  <nobody@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

Back to comp.lang.python | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

How to catch a line with Popen TheSaint <nobody@nowhere.net.no> - 2011-05-29 00:01 +0800
  Re: How to catch a line with Popen Nobody <nobody@nowhere.com> - 2011-05-28 23:15 +0100
  Re: How to catch a line with Popen Tim Roberts <timr@probo.com> - 2011-05-28 16:32 -0700
    Re: How to catch a line with Popen TheSaint <nobody@nowhere.net.no> - 2011-05-29 18:02 +0800
      Re: How to catch a line with Popen Chris Rebert <clp2@rebertia.com> - 2011-05-29 03:26 -0700
        Re: How to catch a line with Popen TheSaint <nobody@nowhere.net.no> - 2011-05-29 21:52 +0800
          Re: How to catch a line with Popen TheSaint <nobody@nowhere.net.no> - 2011-05-29 22:13 +0800
          Re: How to catch a line with Popen Chris Torek <nospam@torek.net> - 2011-05-30 01:02 +0000
            Re: How to catch a line with Popen TheSaint <nobody@nowhere.net.no> - 2011-05-30 23:29 +0800
              Re: How to catch a line with Popen Chris Torek <nospam@torek.net> - 2011-05-30 21:33 +0000
                Re: How to catch a line with Popen TheSaint <nobody@nowhere.net.no> - 2011-05-31 19:33 +0800

csiph-web