2016-07-07 56 views
1

我有一個wxPython應用程序。我希望它對SIGTERM和SIGINT作出響應,就好像「close」按鈕已被點擊一樣。但是,當我使用signal.signal(signal.SIGTERM, exit_handler)綁定信號時,它們只有在事件以圖形方式發送到主應用程序後才能執行(單擊按鈕,打開菜單等)。如何避免這種情況,並在事件發生後立即執行手柄?wxPython處理SIGTERM/SIGINT

的代碼相關部分:

class MyFrame(wx.Frame): 
    def __init__(self, parent, title): 
     # ... 
     self.Bind(wx.EVT_CLOSE, self.signal_handler) 
     signal.signal(signal.SIGTERM, self.signal_handler) 
     signal.signal(signal.SIGINT, self.signal_handler) 

# ... 

app = wx.App(redirect=False, clearSigInt=False) 
frame = MyFrame(None, "Hello World") 
app.MainLoop() 

會發生這種情況,即使信號調用任何功能外側移動和之前的任何WX調用執行。

回答

1

這樣做的一種方法是添加一個'計時器'來僞造一個事件。

import wx 
import signal, os 

def signalUSR1_handler(sig,frame): 
    print "Signal Caught" 

class ExampleFrame(wx.Frame): 
    def __init__(self, parent): 
     wx.Frame.__init__(self, parent) 
     pid_no = str(os.getpid()) 
     panel = wx.Panel(self) 
     self.quote1 = wx.StaticText(panel, label="Test signal with timer", pos=(20, 30)) 
     self.quote2 = wx.StaticText(panel, label="Send this process a USR1 signal", pos=(20, 50)) 
     self.quote3 = wx.StaticText(panel, label="kill -s USR1 "+pid_no, pos=(20, 70)) 
     self.button = wx.Button(panel, -1, "Click", pos=(20,90)) 
     self.button.Bind(wx.EVT_BUTTON, self.OnPress) 
     self.timer = wx.Timer(self) 
     self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer) 
     self.timer.Start(1000) 
     self.Show() 
    def OnPress(self, event): 
     print "Button Pressed" 
    def OnTimer(self, event): 
     return 
app = wx.App() 
ExampleFrame(None) 
signal.signal(signal.SIGUSR1,signalUSR1_handler) 
app.MainLoop() 
+1

爲了幫助您理解爲什麼它的工作方式如此:IIRC,Python中的信號在它們發生時被捕獲,但只在執行Python代碼時被處理。因此,如果在程序在MainLoop中等待某個事件時發生信號,那麼在該事件導致控件返回到Python代碼(例如,將事件分派給Python代碼中的處理程序)之前,什麼也不做。因此,使用計時器如上所述是確保控制離開MainLoop並定期進入Python代碼以便調用信號處理程序的一種方法。 – RobinDunn

+0

@RobinDunn我真的應該在我的回答中解釋說,謝謝! –

相關問題