2009-02-16 16 views
9

Me gustaría usar la versión de subproceso de Python 2.6, porque permite la función Popen.terminate(), pero estoy atascado con Python 2.5. ¿Hay alguna forma razonablemente limpia de usar la versión más nueva del módulo en mi código 2.5? ¿Algún tipo de from __future__ import subprocess_module?Usar el módulo de subproceso Python 2.6 en Python 2.5

+1

Popen.terminate() no funciona correctamente , He encontrado. Ten cuidado. – Brandon

Respuesta

9

Sé que esta pregunta ya ha sido respondida, pero por si sirve de algo, he usado el subprocess.py que viene con Python 2.6 en Python 2.3 y ha funcionado bien. Si has leído los comentarios en la parte superior del archivo que dice:

# This module should remain compatible with Python 2.2, see PEP 291.

+2

PEP 291 es muy útil para conocer. ¡Gracias! (enlace, para la conveniencia de los demás: http://www.python.org/dev/peps/pep-0291/) He decidido que su respuesta responde mi pregunta de manera más precisa, aunque Zacherates también es muy útil. – xyz

+2

Advertencia: esto no es del todo cierto. La implementación del parámetro close_fds en el módulo de subproceso 2.6 usa os.closerange(), que es nuevo en Python 2.6 – itsadok

+0

¡esto me salvó el día! gracias :-) –

0

Well Python es de código abierto, puede tomar esa función pthread desde 2.6 y moverla a su propio código o utilizarla como referencia para implementar la suya propia.

Por razones que deberían ser obvias, no hay forma de tener un híbrido de Python que pueda importar porciones de versiones más nuevas.

6

No hay realmente una buena manera de hacerlo. El subproceso es implemented in python (a diferencia de C) por lo que podría copiar el módulo en alguna parte y usarlo (con la esperanza, por supuesto, de que no use ninguna bondad 2.6).

Por otro lado, podría simplemente implementar lo que dice el subproceso y escribir una función que envíe SIGTERM en * nix y llame a TerminateProcess en Windows. La siguiente aplicación ha sido probado en Linux y en Windows XP VM, debes contar con la 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) 

De esta manera es suficiente para mantener el código terminate en lugar de todo el módulo.

+0

¡Impresionante, muchas gracias! 'ps aux' me dice que el proceso ha desaparecido después de terminarlo con esta función, pero parece que os.waitpid (process.pid, 0) se ocupa de eso. – xyz

2

Si bien esto no responde directamente a su pregunta, puede valer la pena saberlo.

Las importaciones de __future__ en realidad solo cambian las opciones del compilador, por lo tanto, si bien se puede convertir en una declaración o hacer cadenas literales para producir unicodes en lugar de strs, no puede cambiar las capacidades y características de los módulos en la biblioteca estándar de Python.

+0

Entendido, gracias. No lo sabía. – xyz

1

Estas son algunas maneras de terminar los procesos en Windows, tomadas directamente de 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) 
2

I siguió la sugerencia de Kamil Kisiel sobre el uso de python 2.6 subprocess.py en python 2.5 y funcionó perfectamente. Para hacerlo más fácil, creé un paquete de distutils que puedes instalar fácilmente y/o incluir en buildout.

Para utilizar subproceso de Python 2.6 en Python 2.5 proyecto:

easy_install taras.python26 

en el código

from taras.python26 import subprocess 

en buildout

[buildout] 
parts = subprocess26 

[subprocess26] 
recipe = zc.recipe.egg 
eggs = taras.python26 
Cuestiones relacionadas