Snippet: The leanest Popen wrapper

Thomas Rachel nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa915 at spamschutz.glglgl.de
Thu Aug 4 04:24:08 EDT 2011


Am 03.08.2011 17:29 schrieb Phlip:
> Groupies:
>
> This is either a code snippet, if you like it, or a request for a
> critique, if you don't.

Well, at first, I cannot see the real point about it...


> def command(*cmdz):
>
>      process = Popen( flatten(cmdz),
>                       shell= True,
>                       stdout= subprocess.PIPE,
>                       stderr= subprocess.PIPE,
>                       bufsize= 4096 )
>
>      def line():
>          return process.stdout.readline().rstrip()
>
>      def s():
>          while True:
>              l = line()
>              if not l:  break
>              yield l
>
>      line.s = s
>
>      return line

I find it quite ugly. You get a function object with an attached 
generator (which has a strange and non-verbose name and) which might 
stop too early due to an empty line. Plus, you have no real control over 
the communication; you have no access to stdin or stderr. The latter 
might produce a lock if the process writes out too much on stderr.

Plus, you have no access to the exit code of the program.

And you lose information about if the stream ends with any combination 
of whitespace.


> That leads to some syntactic sugar. For example, one truly demented
> way to stream in an entire block and then treat it as one big string
> is this:
>
> print '\n'.join(command('ls').s())

What would work as well via

print Popen( ['ls'], stdout= subprocess.PIPE).stdout.read()
or
print Popen( ['ls'], stdout= subprocess.PIPE).communicate()[0]


> The point of the command() complex is the ability to start a long
> command and then fetch out individual lines from it:
>
> line = command('find', '../..')

sp = Popen( ['find', '../..'], stdout= subprocess.PIPE).stdout.read()
line = sp.stdout.readline
# if you want so: line = lambda: sp.stdout.readline().rstrip() - which
# might lose information as well...

> print 'lines'
> print line()
> print line()
> print line()
>
> print 'all'
> print list(line.s())
print list(iter(line, ''))


Thomas



More information about the Python-list mailing list