Python GTK信号处理程序不起作用 [英] Python GTK signal handler not working

查看:159
本文介绍了Python GTK信号处理程序不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为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 

$ 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆