streaming Popen.stdout

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Michele Simionato

    #1

    streaming Popen.stdout

    I was experimenting with subprocess.Pope n with the following script:

    $ cat Popen_ex.py
    import sys, subprocess
    po = subprocess.Pope n([sys.executable, 'hello.py'],
    stdout=subproce ss.PIPE,
    bufsize=0)
    for line in po.stdout:
    print line,

    where hello.py is the following script:

    $ cat hello.py
    import time
    time.sleep(1)
    print 'hello'
    time.sleep(1)
    print 'world'
    time.sleep(1)
    print '*END*'
    time.sleep(1)

    It turns out that Popen collects all the output and write everything
    together
    after 4 seconds, where I would like to print a line every seconds.
    How can I get that in a simple way? A Unix-only solution would be fine,
    too.


    Michele Simionato

  • Michele Simionato

    #2
    Re: streaming Popen.stdout

    Replying to myself ...

    I cooked up this solution involving os.pipe and os.fork, but I am not
    especially happy with
    it; anyway, let me write it. Feedback is welcome, since this was
    written very quickly and
    I may have missed something. BTW, are there libraries out there doing
    something similar?

    ----

    import subprocess
    import os, sys, time

    class ReadObject(obje ct):
    def __init__(self, fileno):
    self.fileno = fileno
    self._closed = False
    self.name = str(self)
    def readline(self):
    if self._closed : return ''
    return ''.join(iter(se lf.read1, '\n')) + '\n'
    def read(self):
    return ''.join(iter(se lf.read1, '\x00'))
    def read1(self):
    c = os.read(self.fi leno, 1)
    if c == '\x00':
    self._closed = True
    return '\n'
    else:
    return c
    def __iter__(self):
    return iter(self.readl ine, '')

    class WriteObject(obj ect):
    def __init__(self, fileno):
    self.fileno = fileno
    self.name = str(self)
    def write(self, text):
    os.write(self.f ileno, text)
    def flush(self):
    pass
    def close(self):
    self.write('\x0 0')

    def callproc(child, *args,**kw):
    "Run the child procedure in a child process"
    r, w = os.pipe()
    R, W = ReadObject(r), WriteObject(w)
    if os.fork(): # parent
    return R
    else: # child
    sys.stdout = W
    try:
    child(*args, **kw)
    finally:
    W.close()
    sys.exit()

    if __name__ == '__main__':
    for line in callproc(subpro cess.call, [sys.executable,
    'hello.py']):
    print line,

    Comment

    Working...