subprocess.Popen() output to logging.StreamHandler()

Thomas Dimson tdimson at gmail.com
Thu Apr 10 09:59:09 EDT 2008


On Apr 10, 8:11 am, "sven _" <svens... at gmail.com> wrote:
> Version: Python 2.5.1 (r251:54863, Mar  7 2008, 04:10:12)
>
> My goal is to have stdout and stderr written to a logging handler.
> This code does not work:
>
> # START
> import logging, subprocess
> ch = logging.StreamHandler()
> ch.setLevel(logging.DEBUG)
> subprocess.call(['ls', '-la'], 0, None, None, ch, ch)
> # END
>
> Traceback (most recent call last):
>   File "log.py", line 5, in <module>
>    subprocess.call(['ls', '-la'], 0, None, None, ch, ch)
>   File "/usr/lib/python2.5/subprocess.py", line 443, in call
>    return Popen(*popenargs, **kwargs).wait()
>   File "/usr/lib/python2.5/subprocess.py", line 586, in __init__
>    errread, errwrite) = self._get_handles(stdin, stdout, stderr)
>   File "/usr/lib/python2.5/subprocess.py", line 941, in _get_handles
>    c2pwrite = stdout.fileno()
> AttributeError: StreamHandler instance has no attribute 'fileno'
>
> This is because subprocess.Popen() expects file descriptors to write
> to, and logging.StreamHandler() does not supply it. The StreamHandler
> could supply its own stdout file descriptor, but then Popen() would
> write directly to that file, bypassing all the logging fluff.
>
> A possible solution would be to make a named pipe (os.mkfifo()), have
> Popen() write to that, and then have some horrendous hack run select()
> or similar on the fifo to read from it and finally pass it to
> StreamHandler.
>
> Are there better solutions?
>
> sven


What is wrong with doing something like:

import logging, subprocess
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

s = subprocess.Popen( ['ls','-la'], stdout=subprocess.PIPE )
while 1:
    ch.info( s.stdout.readline() )
    if s.poll() == None:
        break

Perhaps not the most efficient or clean solution, but that is how I
usually do it (note: I didn't test the above code).

-Thomas Dimson



More information about the Python-list mailing list