Use Python 2.6 subprocess module in Python 2.5
-
23-08-2019 - |
Question
I would like to use Python 2.6's version of subprocess, because it allows the Popen.terminate() function, but I'm stuck with Python 2.5. Is there some reasonably clean way to use the newer version of the module in my 2.5 code? Some sort of from __future__ import subprocess_module
?
Solution
I know this question has already been answered, but for what it's worth, I've used the subprocess.py
that ships with Python 2.6 in Python 2.3 and it's worked fine. If you read the comments at the top of the file it says:
# This module should remain compatible with Python 2.2, see PEP 291.
OTHER TIPS
There isn't really a great way to do it. subprocess is implemented in python (as opposed to C) so you could conceivably copy the module somewhere and use it (hoping of course that it doesn't use any 2.6 goodness).
On the other hand you could simply implement what subprocess claims to do and write a function that sends SIGTERM on *nix and calls TerminateProcess on Windows. The following implementation has been tested on linux and in a Win XP vm, you'll need the python Windows extensions:
import sys
def terminate(process):
"""
Kills a process, useful on 2.5 where subprocess.Popens don't have a
terminate method.
Used here because we're stuck on 2.5 and don't have Popen.terminate
goodness.
"""
def terminate_win(process):
import win32process
return win32process.TerminateProcess(process._handle, -1)
def terminate_nix(process):
import os
import signal
return os.kill(process.pid, signal.SIGTERM)
terminate_default = terminate_nix
handlers = {
"win32": terminate_win,
"linux2": terminate_nix
}
return handlers.get(sys.platform, terminate_default)(process)
That way you only have to maintain the terminate
code rather than the entire module.
While this doesn't directly answer your question, it may be worth knowing.
Imports from __future__
actually only change compiler options, so while it can turn with into a statement or make string literals produce unicodes instead of strs, it can't change the capabilities and features of modules in the Python standard library.
I followed Kamil Kisiel suggestion regarding using python 2.6 subprocess.py in python 2.5 and it worked perfectly. To make it easier, I created a distutils package that you can easy_install and/or include in buildout.
To use subprocess from python 2.6 in python 2.5 project:
easy_install taras.python26
in your code
from taras.python26 import subprocess
in buildout
[buildout]
parts = subprocess26
[subprocess26]
recipe = zc.recipe.egg
eggs = taras.python26
Here are some ways to end processes on Windows, taken directly from http://code.activestate.com/recipes/347462/
# Create a process that won't end on its own
import subprocess
process = subprocess.Popen(['python.exe', '-c', 'while 1: pass'])
# Kill the process using pywin32
import win32api
win32api.TerminateProcess(int(process._handle), -1)
# Kill the process using ctypes
import ctypes
ctypes.windll.kernel32.TerminateProcess(int(process._handle), -1)
# Kill the proces using pywin32 and pid
import win32api
PROCESS_TERMINATE = 1
handle = win32api.OpenProcess(PROCESS_TERMINATE, False, process.pid)
win32api.TerminateProcess(handle, -1)
win32api.CloseHandle(handle)
# Kill the proces using ctypes and pid
import ctypes
PROCESS_TERMINATE = 1
handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, False, process.pid)
ctypes.windll.kernel32.TerminateProcess(handle, -1)
ctypes.windll.kernel32.CloseHandle(handle)
Well Python is open source, you are free to take that pthread function from 2.6 and move it into your own code or use it as a reference to implement your own.
For reasons that should be obvious there's no way to have a hybrid of Python that can import portions of newer versions.