Added kill, terminate and send_signal to subprocess.Popen

The bits and pieces for the Windows side were already in place. The POSIX side is trivial (as usual) and uses os.kill().
This commit is contained in:
Christian Heimes 2008-04-19 02:23:57 +00:00
parent c873550737
commit e74c8f2879
4 changed files with 103 additions and 0 deletions

View File

@ -208,6 +208,29 @@ Instances of the :class:`Popen` class have the following methods:
size is large or unlimited.
.. method:: Popen.send_signal(signal)
Sends the signal *signal* to the child.
.. note::
On Windows only SIGTERM is supported so far. It's an alias for
*terminate*.
.. method:: Popen.terminate()
Stop the child. On Posix OSs the method sends SIGTERM to the
child. On Windows the Win32 API function TerminateProcess is called
to stop the child.
.. method:: Popen.kill()
Kills the child. On Posix OSs the function sends SIGKILL to the child.
On Windows *kill* is an alias for *terminate*.
The following attributes are also available:
.. attribute:: Popen.stdin

View File

@ -357,6 +357,7 @@ import os
import types
import traceback
import gc
import signal
# Exception classes used by this module.
class CalledProcessError(Exception):
@ -384,6 +385,7 @@ if mswindows:
from win32process import CreateProcess, STARTUPINFO, \
GetExitCodeProcess, STARTF_USESTDHANDLES, \
STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE
from win32process import TerminateProcess
from win32event import WaitForSingleObject, INFINITE, WAIT_OBJECT_0
else:
from _subprocess import *
@ -906,6 +908,21 @@ class Popen(object):
self.wait()
return (stdout, stderr)
def send_signal(self, sig):
"""Send a signal to the process
"""
if sig == signal.SIGTERM:
self.terminate()
else:
raise ValueError("Only SIGTERM is supported on Windows")
def terminate(self):
"""Terminates the process
"""
TerminateProcess(self._handle, 1)
kill = terminate
else:
#
# POSIX methods
@ -1184,6 +1201,21 @@ class Popen(object):
self.wait()
return (stdout, stderr)
def send_signal(self, sig):
"""Send a signal to the process
"""
os.kill(self.pid, sig)
def terminate(self):
"""Terminate the process with SIGTERM
"""
self.send_signal(signal.SIGTERM)
def kill(self):
"""Kill the process with SIGKILL
"""
self.send_signal(signal.SIGKILL)
def _demo_posix():
#

View File

@ -584,6 +584,29 @@ class ProcessTestCase(unittest.TestCase):
os.remove(fname)
self.assertEqual(rc, 47)
def test_send_signal(self):
p = subprocess.Popen([sys.executable,
"-c", "input()"])
self.assert_(p.poll() is None, p.poll())
p.send_signal(signal.SIGINT)
self.assertNotEqual(p.wait(), 0)
def test_kill(self):
p = subprocess.Popen([sys.executable,
"-c", "input()"])
self.assert_(p.poll() is None, p.poll())
p.kill()
self.assertEqual(p.wait(), -signal.SIGKILL)
def test_terminate(self):
p = subprocess.Popen([sys.executable,
"-c", "input()"])
self.assert_(p.poll() is None, p.poll())
p.terminate()
self.assertEqual(p.wait(), -signal.SIGTERM)
#
# Windows tests
@ -655,6 +678,29 @@ class ProcessTestCase(unittest.TestCase):
' -c "import sys; sys.exit(47)"')
self.assertEqual(rc, 47)
def test_send_signal(self):
p = subprocess.Popen([sys.executable,
"-c", "input()"])
self.assert_(p.poll() is None, p.poll())
p.send_signal(signal.SIGTERM)
self.assertNotEqual(p.wait(), 0)
def test_kill(self):
p = subprocess.Popen([sys.executable,
"-c", "input()"])
self.assert_(p.poll() is None, p.poll())
p.kill()
self.assertNotEqual(p.wait(), 0)
def test_terminate(self):
p = subprocess.Popen([sys.executable,
"-c", "input()"])
self.assert_(p.poll() is None, p.poll())
p.terminate()
self.assertNotEqual(p.wait(), 0)
def test_main():
test_support.run_unittest(ProcessTestCase)

View File

@ -18,6 +18,8 @@ Core and builtins
Extensions Modules
------------------
- Added kill, terminate and send_signal(sig) to subprocess.Popen.
- Added phase(z) -> phi, polar(z) -> r, phi and rect(r, phi) -> z to the cmath
module.