Python线程甚至在关闭WxPython应用程序后运行

时间:2013-07-17 15:04:38

标签: python multithreading wxpython

以下代码截取屏幕截图并记录击键和鼠标移动。它使用wxpython作为GUI框架。我正在使用python线程进行截屏和日志记录服务。但每当我关闭GUI应用程序。线程仍在运行。关闭应用程序后如何停止这些线程?

import wx
import threading
import sys
import subprocess
import time

from pymouse import PyMouse
from pymouse import PyMouseEvent
from pykeyboard import PyKeyboard
from pykeyboard import PyKeyboardEvent

import pyscreenshot as ImageGrab
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw 
import gtk.gdk

import urllib2, urllib
import Cookie

MouseMovesCount = 0
MouseClicksCount = 0
KeyStrokesCount = 0

class OD_App(wx.App):
 def OnInit(self):
    frame = OD_MainFrame ("Login", (0, 0), (350, 200))
    self.SetTopWindow(frame)

    loginPanel = OD_LoginPanel (frame)
    self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
    frame.Show()
    return True

 def OnCloseWindow (self, event):
    self.Destroy()

class OD_MainFrame(wx.Frame):
 def __init__(self, title, pos, size):
    wx.Frame.__init__(self, None, -1, title, pos, size)
    self.CreateStatusBar()

class OD_LoginPanel(wx.Panel):
 def __init__(self, frame):  
    self.panel = wx.Panel(frame)
    self.frame = frame

    self.frame.SetStatusText("Authentication required!")
    self.showLoginBox()

 def showLoginBox (self):
  # Create the sizer
    sizer = wx.FlexGridSizer(rows=3, cols=2, hgap=5, vgap=15)

    # Username
    self.txt_Username = wx.TextCtrl(self.panel, 1, size=(150, -1))
    lbl_Username = wx.StaticText(self.panel, -1, "Username:")
    sizer.Add(lbl_Username,0, wx.LEFT|wx.TOP| wx.RIGHT, 50)
    sizer.Add(self.txt_Username,0, wx.TOP| wx.RIGHT, 50)

    # Password
    self.txt_Password = wx.TextCtrl(self.panel, 1, size=(150, -1), style=wx.TE_PASSWORD)
    lbl_Password = wx.StaticText(self.panel, -1, "Password:")
    sizer.Add(lbl_Password,0, wx.LEFT|wx.RIGHT, 50)
    sizer.Add(self.txt_Password,0, wx.RIGHT, 50)

    # Submit button
    btn_Process = wx.Button(self.panel, -1, "&Login")
    self.panel.Bind(wx.EVT_BUTTON, self.OnSubmit, btn_Process)
    sizer.Add(btn_Process,0, wx.LEFT, 50)

    self.panel.SetSizer(sizer)

 def OnSubmit(self, event):
    username = self.txt_Username.GetValue()
    password = self.txt_Password.GetValue()
    mydata = [('username',username),('password',password)]
    mydata = urllib.urlencode(mydata)
    path = 'http://xyz/logincheck.php'    #temporary db for testing
    req = urllib2.Request(path, mydata)
    req.add_header("Content-type", "application/x-www-form-urlencoded")
    page = urllib2.urlopen(req).read()
    if page == "true":
      self.frame.SetStatusText("Authentication Success!")
      self.show_other(username)
    else:
      self.frame.SetStatusText("Authentication Failed!")

 def OnCloseWindow (self, event):
    self.Destroy()

 def show_other(self,username):
    self.frame.Destroy()
    userpanel = OD_UserPanel()
    return True

class OD_UserPanel(wx.App):
 def OnInit(self):
    userpanel = wx.Frame(None,-1)
    self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
    #user_greeting = 'Welcome ' + username + '!'
    #username = wx.StaticText(userpanel, -1, user_greeting , style=wx.ALIGN_CENTRE)
    userpanel.Show()
    mouse_eventer = mouse_event()
    mouse_eventer.start()
    keyboard_eventer = key_event()
    keyboard_eventer.start()
    screenshot_eventer = screenshot_thread()
    screenshot_eventer.start()
    return True
 def OnCloseWindow (self, event):
    quit()
    event.Skip()
    raise SystemExit
class mouse_event(PyMouseEvent):
    def move(self, x, y):
        global MouseMovesCount
        MouseMovesCount = MouseMovesCount + 1
        print MouseMovesCount
    def click(self, x, y, button, press):
        global MouseClicksCount
            if press:
        MouseClicksCount = MouseClicksCount + 1
                print MouseClicksCount
            else:
                MouseClicksCount = MouseClicksCount + 1
                print MouseClicksCount

class key_event(PyKeyboardEvent):
    global screenshot_eventer
    def key_press(self, key):
        global KeyStrokesCount
        KeyStrokesCount = KeyStrokesCount + 1
        print KeyStrokesCount
    def key_release(self, key):
        global KeyStrokesCount
        KeyStrokesCount = KeyStrokesCount + 1
        print KeyStrokesCount

class screenshot_thread(threading.Thread):
  def __init__(self):
    super(screenshot_thread, self).__init__()
    self.state = True
  # Attributes
  def run(self):
    self.take_shot()
  def stop(self):
    self.state = False
    threading.Thread._Thread__stop()
  def take_shot(self):
     while self.state==True:
    time.sleep(10)
    subprocess.call(['scrot'])
if __name__ == '__main__':
    app = OD_App()
    app.MainLoop()

2 个答案:

答案 0 :(得分:2)

请勿致电threading.Thread._Thread__stop!前导下划线表示这是内部api,它甚至不能保证存在(事实上,在python3中它已经消失了)。

如果您希望自动销毁thead,请将其设置为daemonic:

def __init__(self):
    super(screenshot_thread, self).__init__()
    self.daemon = True

这将导致在最后一个非守护程序线程停止时自动销毁它。或者,在您的情况下,只需将状态设置为False即可使线程在10秒后退出。

答案 1 :(得分:0)

您在stop课程中定义了screenshot_thread方法,但您没有使用它。在方法OnCloseWindow中调用它应该可以胜任。