¿Cómo lograr los resultados deseados al usar los subprocesos Popen.send_signal (CTRL_C_EVENT) en Windows?

En Python 2.7 en Windows, de acuerdo con la documentación, puede enviar una documentación CTRL_C_EVENT (Python 2.7 Subprocess Popen.send_signal). Sin embargo, cuando lo probé no recibí la interrupción de teclado esperada en el subproceso.

Este es el código de ejemplo para el proceso padre:

# FILE : parentProcess.py import subprocess import time import signal CREATE_NEW_PROCESS_GROUP = 512 process = subprocess.Popen(['python', '-u', 'childProcess.py'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, creationflags=CREATE_NEW_PROCESS_GROUP) print "pid = ", process.pid index = 0 maxLoops = 15 while index < maxLoops: index += 1 # Send one message every 0.5 seconds time.sleep(0.5) # Send data to the subprocess process.stdin.write('Bar\n') # Read data from the subprocess temp = process.stdout.readline() print temp, if (index == 10): # Send Keyboard Interrupt process.send_signal(signal.CTRL_C_EVENT) 

Este es el código de ejemplo para el proceso hijo:

 # FILE : childProcess.py import sys while True: try: # Get data from main process temp = sys.stdin.readline() # Write data out print 'Foo ' + temp, except KeyboardInterrupt: print "KeyboardInterrupt" 

Si ejecuto el archivo parentProcess.py espero obtener “Foo Bar” diez veces y luego un “Interruptor de teclado” seguido de “Foo Bar” 4 veces, pero recibo “Foo Bar” 15 veces.

¿Hay alguna manera de hacer que CTRL_C_EVENT se comporte como una interrupción del teclado, igual que SIGINT se comporta en Linux?

Después de leer un poco, encontré información que parece contradecir la documentación de python relacionada con CTRL_C_EVENT, en particular, dice que

CTRL_C_EVENT 0 Genera una señal CTRL + C. Esta señal no puede ser generada para grupos de proceso.

El siguiente sitio proporciona más información sobre los indicadores de creación: Indicadores de creación de procesos.

Este método de manejo de señal por subprocesos funcionó para mí tanto en Linux como en Windows 2008, ambos usando Python 2.7.2, pero usa Ctrl-Break en lugar de Ctrl-C. Consulte la nota sobre grupos de procesos y Ctrl-C en http://msdn.microsoft.com/en-us/library/ms683155%28v=vs.85%29.aspx .

catcher.py:

 import os import signal import sys import time def signal_handler(signal, frame): print 'catcher: signal %d received!' % signal raise Exception('catcher: i am done') if hasattr(os.sys, 'winver'): signal.signal(signal.SIGBREAK, signal_handler) else: signal.signal(signal.SIGTERM, signal_handler) print 'catcher: started' try: while(True): print 'catcher: sleeping...' time.sleep(1) except Exception as ex: print ex sys.exit(0) 

thrower.py:

 import signal import subprocess import time import os args = [ 'python', 'catcher.py', ] print 'thrower: starting catcher' if hasattr(os.sys, 'winver'): process = subprocess.Popen(args, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP) else: process = subprocess.Popen(args) print 'thrower: waiting a couple of seconds for catcher to start...' time.sleep(2) print 'thrower: sending signal to catch' if hasattr(os.sys, 'winver'): os.kill(process.pid, signal.CTRL_BREAK_EVENT) else: process.send_signal(signal.SIGTERM) print 'thrower: i am done' 

tratar con

 win32api.GenerateConsoleCtrlEvent(CTRL_C_EVENT, pgroupid) 

o

 win32api.GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pgroupid) 

referencias:

http://docs.activestate.com/activepython/2.5/pywin3/win32process_CREATE_NEW_PROCESS_GROUP.html

http://msdn.microsoft.com/en-us/library/ms683155%28v=vs.85%29.aspx

lea la información sobre dwProcessGroupId, el ID de grupo debe ser el mismo que el ID de proceso