[Python 2.4/2.5] subprocess module is sorely deficient?

Nick Craig-Wood nick at craig-wood.com
Tue Apr 22 08:30:02 EDT 2008


Harishankar <v.harishankar at gmail.com> wrote:
>  Sorry to start off on a negative note in the list, but I feel that the Python 
>  subprocess module is sorely deficient because it lacks a mechanism to:
> 
>  1. Create non-blocking pipes which can be read in a separate thread (I am 
>  currently writing a mencoder GUI in Tkinter and need a full fledged process 
>  handler to control the command line and to display the progress in a 
>  text-box)
> 
>  2. Kill the subprocess in a platform independent manner (i.e. no third party 
>  modules and no hacks).

You are correct on both of those points.  Subprocess isn't for
interacting with subprocesses - this should be written in large
letters in the help!

>  Is there any way to use non-blocking Popen objects using
>  subprocess?

There is a recipe in the cookbook

  http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554

Which I've used and it works.

you can also (if on unix) use

  http://www.noah.org/wiki/Pexpect

I think the best solution would be to port Pexpect to windows which
wouldn't be that difficult according to my reading of the code.  If
only I had more free time!

>  and 2 - is there a way to kill the subprocess in a platform
>  independent manner in a purely Pythonic way? I thought initially
>  that this problem is simple enough, but over the last couple of
>  days I've been really struggling to find any answer. I've been
>  through dozens of mailing list archives in to find a
>  solution. Unfortunately none of the solutions seem to fit my needs.

No...

This is the best I came up with to add to the subprocess recipe above

import os
from subprocess import *
from subprocess import mswindows
from time import sleep

if mswindows:
    import win32api
else:
    import signal

class PopenNB(Popen):
    # - see cookbook recipe for rest of stuff
    # ...
    def kill(self, killpg=False):
        """
        Kill the running process
        """
        pid = self.pid
        if mswindows:
            # Kill the process using win32api and pid - ignore errors
            try:
                PROCESS_TERMINATE = 1
                handle = win32api.OpenProcess(PROCESS_TERMINATE, False, pid)
                win32api.TerminateProcess(handle, -1)
                win32api.CloseHandle(handle)
            except pywintypes.error:
                pass
        else:
            # Kill the process by sending the pid / process group a
	    signal
            if killpg:
                try:
                    pgid = os.getpgid(pid)
                except OSError:
                    killpg = False
            try:
                if killpg:
                    os.killpg(pgid, signal.SIGTERM)
                else:
                    os.kill(pid, signal.SIGTERM)
            except OSError:
                return
            sleep(1.0)
            try:
                if killpg:
                    os.killpg(pgid, signal.SIGKILL)
                else:
                    os.kill(pid, signal.SIGKILL)
            except OSError:
                return

-- 
Nick Craig-Wood <nick at craig-wood.com> -- http://www.craig-wood.com/nick



More information about the Python-list mailing list