在Windows中使用信号中断python multiprocessing.Process

时间:2016-10-26 15:48:18

标签: python windows signals python-multiprocessing

我有一个python脚本,它使用multiprocessing.Process类生成一个新的Process。这个过程应该永远运行以监控东西。在Unix上,我现在可以使用os.kill()向该特定进程发送信号,并在该进程中发送signal.signal(...)以实现我的特定中断处理程序。在Windows上,事情不起作用。

我看了如何使用popen来做到这一点。我也可以为Process类指定CREATE_NEW_PROCESS_GROUP标志吗?怎么样?

这是我的示例代码:

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

1 个答案:

答案 0 :(得分:1)

我找到了一种解决方法,使用multiprocessing.Event类实现信号传输。

然后找到interrupt_main()方法(在thread(Python2)或_thread(Python3)中)的线索,它在主线程中引发KeybordInterrupt,这是进程我想打断。

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