2016-10-26 7 views
1

Ich habe ein Python-Skript, das einen neuen Prozess mit Multiprocessing.Process-Klasse erzeugt. Dieser Prozess soll für immer laufen, um Dinge zu überwachen. Unter Unix kann ich jetzt os.kill() verwenden, um ein Signal an diesen spezifischen Prozess zu senden, und signal.signal (...) innerhalb dieses Prozesses, um meinen speziellen Interrupt-Handler zu implementieren. Unter Windows funktionieren die Dinge nicht.Interrupt Python Multiprocessing.Process mit Signalen in Windows

Ich lese, wie es mit popen funktioniert. Kann ich das CREATE_NEW_PROCESS_GROUP-Flag für die Process-Klasse auch angeben? und wie?

hier ist mein Beispielcode:

import multiprocessing as mp 
import time 
import signal 
import os 
import platform 

def my_h(signal, frame): 
    print("recieved signal", signal) 
    raise InterruptedError 

def a_task(): 
    signal.signal(signal.SIGINT, my_h) 
    print("this is 'a_task'", os.getpid()) 
    try: 
     while True: 
      print(time.time()) 
      time.sleep(1) 
    except Exception as e: 
     print(type(e), e) 
    print("'a_task' is at end") 


if __name__ == '__main__': 
    p = mp.Process(target=a_task) 
    p.start() 
    time.sleep(1) 

    if platform.system() == 'Windows': 
     print("send CTRL_C_EVENT") 
     os.kill(p.pid, signal.CTRL_C_EVENT) 
    elif platform.system() == 'Linux': 
     print("send SIGINT") 
     os.kill(p.pid, signal.SIGINT) 

    time.sleep(3) 
    try: 
     os.kill(p.pid, signal.SIGTERM) 
    except: 
     pass 
+0

vielleicht dies: http://tweaks.com/windows/39559/kill-processes-from-command-prompt/ –

+0

Ich denke, die andere Lösung Ihr Problem zu beheben. http://StackOverflow.com/Questions/1230669/subprocess-Deleting-Child-Processes-in-Windows#4229404 – mydaemon

+0

Es geht nicht einfach über den Prozess zu beenden, sondern sicherzustellen, dass die 'except' -Klausel vor dem Stoppen – cima

Antwort

1

ich eine Abhilfe gefunden, sorta Implementierung Signalisierungs multiprocessing.Event Klasse.

Der Hinweis war dann interrupt_main() Methode zu finden, die in dem Hauptfaden hebt KeybordInterrupt (die entweder in thread (Python2) oder _thread (Python3) ist), die der Prozess I zu unterbrechen will, ist.

import multiprocessing as mp 
import time 
import signal 
import os 
import threading 
import _thread 

def interrupt_handler(interrupt_event): 
    print("before wait") 
    interrupt_event.wait() 
    print("after wait") 
    _thread.interrupt_main() 

def a_task(interrupt_event, *args): 
    task = threading.Thread(target=interrupt_handler, args=(interrupt_event,)) 
    task.start() 

    print("this is 'a_task'", os.getpid()) 
    try: 
     while True: 
      print(time.time()) 
      time.sleep(1) 
    except KeyboardInterrupt: 
     print("got KeyboardInterrupt") 
    print("'a_task' is at end") 


if __name__ == '__main__': 
    interrupt_event = mp.Event() 
    p = mp.Process(target=a_task, args = (interrupt_event, tuple())) 
    p.start() 
    time.sleep(2) 
    print("set interrupt_event") 
    interrupt_event.set() 

    time.sleep(3) 
    try: 
     os.kill(p.pid, signal.SIGTERM) 
    except: 
     pass 
+0

Dies funktioniert, aber in der Regel würde der Hauptthread in jedem Prozess auf das Ereignis warten oder das Ereignis regelmäßig abfragen und ein Zeichen setzen, dass Worker-Threads ordnungsgemäß beendet werden. Dies kann so einfach wie ein globaler Boolescher Wert sein. – eryksun

+0

Nun, das war meine erste Idee auch. Aber denken Sie an eine Aufgabe, die schon seit geraumer Zeit Zahlen verarbeitet. Wenn ich diesen Prozess unterbrechen möchte, würde das bedeuten, den Worker (nicht Haupt) Thread zu unterbrechen. Ich habe keinen Weg gefunden, wenn der Arbeiter nicht reagiert. Unter Unix sende ich SIGINT und fange es mit Versuch außer. Die obige Lösung ist dem Unix-Arbeitsablauf etwas ähnlich, weshalb ich sie benutzt habe. Aber danke für die Kommentare. – cima

+0

Ich würde erwarten, dass ernsthaftes Zahlen-Crunching auf eine C-Erweiterung ausgelagert wird, und in dieser Hinsicht haben die meisten eingebauten Funktionen schlechte bis keine Unterstützung für die Unterbrechung. Sie geben die GIL frei und gehen los, um ihr eigenes Ding zu machen. Wenn es der Hauptthread ist, dann werden Sie abgespritzt, weil Python Signale darauf verarbeitet - daher die 'interrupt_main'-Funktion, die ein Flag für den Interpreter setzt, wenn es auf dem Hauptthread läuft. – eryksun