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