subprocess vs. proctools

Keith Dart kdart at kdart.com
Tue Dec 14 08:13:02 EST 2004


Nick Craig-Wood wrote:
> Keith Dart <kdart at kdart.com> wrote:
> 
>> Oh, I forgot to mention that it also has a more user- and 
>> programmer-friendly ExitStatus object that processess can return. This 
>> is directly testable in Python:
>>
>> proc = proctools.spawn("somecommand")
>> exitstatus = proc.wait()
>>
>> if exitstatus:
>> 	print "good result (errorlevel of zero)"
>> else:
>>      print exitstatus # prints message with exit value
> 
> 
> This sounds rather like the new subprocess module...
> 
> 
>>>>import subprocess
>>>>rc = subprocess.call(["ls", "-l"])
> 
> total 381896
> -rw-r--r--    1 ncw ncw      1542 Oct 12 17:55 1
> [snip]
> -rw-r--r--    1 ncw ncw       713 Nov 16 08:18 z~
> 
>>>>print rc
> 
> 0

But this evaluates to False in Python, but True in a shell. It also 
requires an extra check for normal exit, or exit by a signal. The 
proctools ExitStatus object avaluates to True only on a normal exit, 
period. Thus it follows a shell semantics for clarity. You cannot do 
this with the subprocess module:

if rc:
     print "exited normally"


But in proctools, the exitstatus is an object that evaluates True only 
for normal exit.

import proctools
proc = proctools.spawnpipe("ls -l")
print proc.read()
  ....
print proc.exitstatus
ls: Exited normally.


proc = proctools.spawnpipe("ls -l xx")
print proc.read()
'ls: xx: No such file or directory\n'

print proc.exitstatus
ls: Exited abnormally with status 1.

if proc.exitstatus:
     print "returned normally"


But you can get the integer return value, if you want it, like this:
int(proc.exitstatus)

or query it with methods returning booleans:

exitstatus.exited()
exitstatus.signalled()
exitstatus.stopped()

Also, proctools lets you use a pty, if you choose. Not every program 
works well from a pipe.

> 
> IMHO the new subprocess module is a very well thought out interface...

The proctools Process object presents a file-like object to the rest of 
Python, which makes a process polymorhic with any other file, pipe or 
socket object. It has the usual read, write, readline, and readlines 
methods. It can also be made non-blocking, and you can have many open at 
once. In addition, there are special methods for controlling the 
sub-process: You can kill it, stop it, re-start it, clone it, wait on 
it, and get stats from it. The stat() method returns a ProcStat object, 
which has attributes like what you get from the 'ps' program. Need to 
know the process's RSS? No problem. It also supports logging to a log 
file, and on-exit callback for persistent process requirements.

You always invoke the spawn* functions with a string. This is parsed by 
a shell-like parser (the shparser module that comes with it), but no 
/bin/sh is invoked. The parser can handle single and double quotes, and 
backslash escapes.

Alas, one thing the proctools module does not do well yet is create a 
pipeline. I have plans to fix that.

It does not work with MS Windows, but can work with cygwin on Windows.


Whew... and I have not even covered the ProcessManager object...



-- 
                            \/ \/
                            (O O)
-- --------------------oOOo~(_)~oOOo----------------------------------------
Keith Dart <kdart at kdart.com>
vcard: <http://www.kdart.com/~kdart/kdart.vcf>
public key: ID: F3D288E4       URL: <http://www.kdart.com/~kdart/public.key>
============================================================================



More information about the Python-list mailing list