Python GTK信号处理程序不起作用 [英] Python GTK signal handler not working
问题描述
我正在为GUI使用GTK编写一个Python应用程序。我注意到用Ctrl-C从终端关闭它并不工作,我发现这是由于一个错误,所以我试图手动处理信号。问题是,如果我将默认行为设置为默认行为,则会捕获信号并正确关闭应用程序,但如果使用自定义处理程序,则不起作用。这里是我的(简体)代码:
from gi.repository import Gtk
导入信号
class MainWindow(Gtk.Window):
def __init __(self):
...
signal.signal(signal.SIGINT,self .__ signal_handler)
def __signal_handler(self,signal,frame):
printCaught!
...
if __name__ ==__main__:
win = MainWindow()
win.show_all()
Gtk .main()
如果我设置默认行为,信号被正确捕获:
from gi.repository import Gtk
导入信号
class MainWindow(Gtk.Window) :
def __init __(self):
...
signal.signal(signal.SIGINT,signal.SIG_DFL)
...
if __name__ ==__main__:
win = MainWindow()
win.show_all()
Gtk.main()
我错过了什么吗?
编辑:
我试了一些,发现信号实际上是被捕获的,但窗口是不是立即关闭,而只是在重新获得焦点时。相反,如果我运行一个
kill -9 pid
$ p
$ b从另一个终端窗口中,应用程序立即关闭。 我还记得在使用pygtk3学习appindicators时,在处理信号时遇到了很多麻烦。这里有一个演示如何为SIGHUP,SIGINT和SIGTERM完成的工作示例:
$ b#!/ usr / bin / python
from gi.repository import gtk,GLib,GObject
from gi.repository import AppIndicator3 as appindicator
import os
import signal
$ b $ class gui():
def __init __(self):
self.window = Gtk.Window(title =Signal example)
self.window.set_size_request(250,150)
self.window.connect (delete-event,Gtk.main_quit)
self.window.show_all()
def cleanup(self):
print(...清理变量,等等)
def quit(self,widget):
print(...退出主gtk循环)
Gtk.main_quit()
$ $ b $ def InitSignal(gui):
def signal_action(信号):
如果信号是1:
print(Caught signal SIGHUP(1))
elif信号是2:
print(捕获信号SIGINT(2))
elif信号(15)
gui.cleanup()
gui.quit(无)
def idle_handler(* args ):
print(Python signal handler activated。)
GLib.idle_add(signal_action,priority = GLib.PRIORITY_HIGH)
def处理程序(* args):
print(GLib signal handler activated。)
signal_action(args [0])
def install_glib_handler(sig):
unix_signal_add = None
如果hasattr(GLib,unix_signal_add):
unix_signal_add = GLib.unix_signal_add
elif hasattr(GLib,unix_signal_add_full):
unix_signal_add = GLib.unix_signal_add_full
如果unix_signal_add:
print(Register GLib signal handler:%r%sig)
unix_signal_add(GLib.PRIORITY_HIGH,sig,handler,sig)
else:
print( 无法安装GLib信号处理程序,太旧的gi。)
SIGS = SIGET SIGTERM SIGHUP中的s的getattr(signal,s,None).slit()]
用于过滤器中的sig(None,SIGS):
print(Register Python signal handler: %b
signal.signal(sig,idle_handler)
GLib.idle_add(install_glib_handler,sig,priority = GLib.PRIORITY_HIGH)
if __name__ ==__main__ :
gui = Gui()
InitSignal(gui)
Gtk.main()
请注意,当接收到信号时,如果您不退出gtk循环(Gtk.main_quit()),那么当它第二次收到信号时,它将自行关闭,可能是因为错误提及。但是,在退出之前清理变量(包括使用CTRL + C)仍然可以完美。
如果我没有记错,我从pygtk irc频道的人那里得到了解决方案,所以我不能给给我提供解决方案的人以正确的信用。I am writing a Python application using GTK for the GUI. I noticed that closing it with Ctrl-C from the terminal isn't working and I discovered this is because of a bug, so I tried to manually handle the signal. The problem is that if I set the default behaviour to the default one, the signal is caught and the application is closed correctly, but if I use a custom handler it doesn't work. Here is my (simplified) code:
from gi.repository import Gtk import signal class MainWindow(Gtk.Window): def __init__(self): ... signal.signal(signal.SIGINT, self.__signal_handler) def __signal_handler(self, signal, frame): print "Caught!" ... if __name__ == "__main__": win = MainWindow() win.show_all() Gtk.main()
If, instead, I set the default behaviour, the signal is caught correctly:
from gi.repository import Gtk import signal class MainWindow(Gtk.Window): def __init__(self): ... signal.signal(signal.SIGINT, signal.SIG_DFL) ... if __name__ == "__main__": win = MainWindow() win.show_all() Gtk.main()
Am I missing something?
EDIT:
I tried some more and I noticed that the signal is actually captured, but the window is not shutdown immediately, but only when the focus has been acquired again. If, instead, I run a
kill -9 pid
from another terminal window, the application is closed immediately.
解决方案I also remember having lots of trouble regarding signal handling while learning appindicators with pygtk3. Here a working example demonstrating how it can be done for SIGHUP, SIGINT and SIGTERM:
#!/usr/bin/python from gi.repository import Gtk, GLib, GObject from gi.repository import AppIndicator3 as appindicator import os import signal class Gui(): def __init__(self): self.window = Gtk.Window(title="Signal example") self.window.set_size_request(250,150) self.window.connect("delete-event", Gtk.main_quit) self.window.show_all() def cleanup(self): print("... Cleaning up variables, etc.") def quit(self, widget): print("... Exiting main gtk loop") Gtk.main_quit() def InitSignal(gui): def signal_action(signal): if signal is 1: print("Caught signal SIGHUP(1)") elif signal is 2: print("Caught signal SIGINT(2)") elif signal is 15: print("Caught signal SIGTERM(15)") gui.cleanup() gui.quit(None) def idle_handler(*args): print("Python signal handler activated.") GLib.idle_add(signal_action, priority=GLib.PRIORITY_HIGH) def handler(*args): print("GLib signal handler activated.") signal_action(args[0]) def install_glib_handler(sig): unix_signal_add = None if hasattr(GLib, "unix_signal_add"): unix_signal_add = GLib.unix_signal_add elif hasattr(GLib, "unix_signal_add_full"): unix_signal_add = GLib.unix_signal_add_full if unix_signal_add: print("Register GLib signal handler: %r" % sig) unix_signal_add(GLib.PRIORITY_HIGH, sig, handler, sig) else: print("Can't install GLib signal handler, too old gi.") SIGS = [getattr(signal, s, None) for s in "SIGINT SIGTERM SIGHUP".split()] for sig in filter(None, SIGS): print("Register Python signal handler: %r" % sig) signal.signal(sig, idle_handler) GLib.idle_add(install_glib_handler, sig, priority=GLib.PRIORITY_HIGH) if __name__ == "__main__": gui = Gui() InitSignal(gui) Gtk.main()
Note that when recieving a signal, if you don't exit gtk loop (Gtk.main_quit()) then when it recieves a signal for the second time it will close itself, probably because of the bug you mentioned. Nontheless for cleaning up variables right before exiting (including with CTRL + C) still works perfect.
If I recall correctly I got the solution from a person in pygtk irc channel, so I cannot give the right credit to the person that provided me with the solution.
这篇关于Python GTK信号处理程序不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!