如何注册一个SIGINT处理程序,它会在按下Ctrl + C后立即运行?

时间:2018-03-04 05:47:05

标签: python signals core-foundation pyobjc runloop

我正在编写一个Python脚本,它使用AppO的PyObjC绑定。该脚本向共享的NSWorkspace notificationCenter注册观察者,然后调用AppKit.CFRunLoopRun()以便处理通知:

from __future__ import print_function
from AppKit import *
import signal

shared_workspace = NSWorkspace.sharedWorkspace()

def on_did_activate_application(notification):
    print('on_did_activate_application(notification = %s)' % notification)

notification_center = shared_workspace.notificationCenter()
did_activate_application_observer = notification_center.addObserverForName_object_queue_usingBlock_(
        NSWorkspaceDidActivateApplicationNotification,
        None,
        None,
        on_did_activate_application)

def handle_interrupt(signum, frame):
    notification_center.removeObserver_(did_activate_application_observer)
    CFRunLoopStop(CFRunLoopGetCurrent())

signal.signal(signal.SIGINT, handle_interrupt)

CFRunLoopRun()

我遇到的问题(可以通过上面的MCVE重现)是,当我在运行脚本的终端窗口上按Ctrl + C时,handle_interrupt()不会立即执行,而是在下次执行时{{{ 1}}通知已处理。

如何在出现后立即响应Ctrl + C / SIGINT?

1 个答案:

答案 0 :(得分:0)

这可以通过将“信号唤醒fd”设置为管道的写入端,然后创建监视管道读取结束活动的CFFileDescriptor来实现。

What’s New in Python 2.6所述,在Python 2.6中,android{ packagingOptions { exclude 'META-INF/DEPENDENCIES' } } 模块中添加了一个名为set_wakeup_fd()的新API。只要收到信号,就会将一个NUL字节(signal)写入fd。

如果将wakeup fd设置为管道的写入端,则可以创建'\0'来监视管道读取端的活动(数据的可用性),并且可以对此类活动进行回调配置为在CFFileDescriptor上运行。

CFRunLoop
致谢

非常感谢'A GUEST'(无论你是谁)发布this paste on Pastebin;致Da_Blitz撰写Fighting set_wakeup_fd文章;以及Stack Overflow上的“Proper” way to handle signals other than SIGINT in Python?What's the difference between SIGSTOP and SIGTSTP?python Non-block read file的askers / anskers。