我正在编写一个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?
答案 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。