1

以下代码截取屏幕截图并记录击键和鼠标移动。它使用 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()
4

2 回答 2

2

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

如果您希望自动销毁thead,请将其设置为守护进程:

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

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

于 2013-07-17T15:25:34.950 回答
0

您在类中定义了一个stop方法,screenshot_thread但您没有使用它。在方法中调用它OnCloseWindow应该可以完成这项工作。

于 2013-07-19T16:44:37.013 回答