Envíe SIGINT al subproceso de Python usando os.kill como si presionara Ctrl + C

Utilizando python 3.4 en windows.
Estoy tratando de terminar el procesamiento de un niño simulando a una persona presionando Ctrl + C (Ctrl + D en Linux).

Acabo de agregar el controlador para comprobar si la señal se estaba manejando. Utilicé la idea de esta pregunta.

El objective es capturar el Interruptor de teclado (SIGINT) y liberar los recursos. Pero parece que la excepción no se produce si SIGINT no proviene del teclado. Es por eso que creé un controlador, pero el proceso no parece ejecutar el controlador en absoluto …

import multiprocessing import time import signal import signal import os import sys def handler(signal, frame): print("handler!!!") sys.exit(10) def worker(): p = multiprocessing.current_process() try: signal.signal(signal.SIGINT,handler) print("[PID:{}] acquiring resources".format(p.pid)) while(True): #working... time.sleep(0.5) except (KeyboardInterrupt, SystemExit): pass finally: print("[PID:{}] releasing resources".format(p.pid)) if __name__ == "__main__": lst = [] for i in range(1): p = multiprocessing.Process(target=worker) p.start() lst.append(p) time.sleep(3) for p in lst: os.kill(p.pid,signal.SIGINT) p.join() print(p) print(p.exitcode) print("joined all processes") 

Aquí hay un ejemplo de la salida:

 C:\Users\Rui>python test.py [PID:16524] acquiring resources  2 joined all processes 
  • ¿Qué estoy haciendo mal?
  • ¿Debo usar el módulo de subproceso?
  • ¿Qué otros enfoques podría intentar interrumpir la ejecución de un proceso?

No funciona porque no puedes usar os.kill para enviar señales arbitrarias en Windows:

os.kill(pid, sig)

Enviar señal sig al proceso pid. Las constantes para las señales específicas disponibles en la plataforma de host se definen en el módulo de señal.

Windows: las señales signal.CTRL_C_EVENT y signal.CTRL_BREAK_EVENT son señales especiales que solo pueden enviarse a los procesos de consola que comparten una ventana de consola común, por ejemplo, algunos subprocesos. Cualquier otro valor para sig causará que el proceso sea cancelado incondicionalmente por la API TerminateProcess , y el código de salida se establecerá en sig . La versión de Windows de kill() adicionalmente toma los manejadores de procesos para ser eliminados.

Las únicas señales que se pueden enviar a través de os.kill son signal.CTRL_C_EVENT y signal.CTRL_BREAK_EVENT . Cualquier otra cosa simplemente termina el proceso, que es lo que está sucediendo en su caso. El uso de signal.CTRL_C_EVENT tampoco funcionará aquí, porque los procesos se iniciaron mediante el multiprocessing.Process no es “procesos de consola que comparten una ventana de consola común” con el padre. No estoy seguro de que haya mucho que puedas hacer aquí con señales en Windows; No parece que tengas permitido capturar TerminateProcess la misma manera que puedes capturar SIGTERM en Unix, por lo que no puedes hacer ninguna limpieza antes de que finalice el proceso, y no estás usando una aplicación de consola para el niño. así que la signal.*_EVENT no funcionará.

Creo que sus opciones son: 1) Use el módulo de subprocess e inicie el proceso hijo con shell=True , lo que creo que significará signal.CTRL+C+EVENT funcionará. 2) Quédese con el módulo de multiprocessing y use un método “cooperativo” para interrumpir al trabajador, como multiprocessing.Event . multiprocessing.Event .