pynput模块: 控制监控鼠标和键盘 2018/11/12 目录: 1.pynput.mouse模块说明 2.pynput.keyboard模块说明 3.样本实例 3.1.控制键盘 3.2.监控键盘 3.3.监控鼠标 4.1.键盘监听-写入日志文件 4.2.鼠标监控封装类-event(暂停,启动,停止) 4.3.鼠标监控封装类(暂停,启动,停止)-线程挂起 4.4.键盘监听(字符,汉字) - 函数实现 4.5.键盘监听(字符,汉字)- 类实现 说明: 1.如何程序有GUI界面,最好不要用此方法。你可以用绘图界面中相应的键盘鼠标 监控函数,相对来说比较容易。如Matplotlib,或Pyqt5都可以。 2.如果程序 中没有界面,还想进行监控,就必须得用,相对来说比较难理解。 3.用途: 你能在我简单封装的基础上做改进,比如输入'run'或'运行'启动一个程序,输入'stop'停止程序。 参考: https://pynput.readthedocs.io/en/latest/_modules/pynput/mouse/_base.html#Listener ===============================================================================
1.模块函数 1.mouse: 包含鼠标类的模块 1.1.class Button: #鼠标的键值类 # left(左键), right(右键),middle(中间建),unknown(未知键) 1.2.class Controller: #向系统发送鼠标事件的控制器 # position: 指针当前的位置 # move(x, y): 将鼠标移动到指定位置 # press(button): 按下鼠标键 # release(button): 释放鼠标键 # scroll(x, y): 发送滚动事件 # click(button, count=1): 在当前位置发送点击事件 # button: 按下的鼠标键 # count: 点击的次数 1.3.class Listener: 鼠标的监听器 Listener(no_move,on_click,on_scroll):#创建一个监听器 no_move: #鼠标移动调用的方法(参数: x, y) on_click: #鼠标点击调用的方法(参数: x, y, button, pressed) on_scroll: #鼠标滚轮滑动调用的方法(参数: x, y , dx, dy) # 方法: run(): #启动监听器 stop(): # 停止监听器 wait(): # 等待监听器就绪 join(): #启动并等待线程停止 =========================================================================== 2.keyboard: 包含键盘类的模块 2.1.class Key: 键盘的键值类 # alt(Alt),alt_l(左Alt),alt_r(右),ctrl(Ctrl),ctrl_l(左Ctrl),ctrl_r(右Ctrl),shift(Shift), enter(回车), # shift_r(右Shift),space(空格),tab(Tab),caps_lock(大小写),cmd(cmd),backspace(退格), # esc(esc),down(下),up(上),left(左),right(右)end(End),delete(Del),home(Home),insert(Ins), # page_down(PageDown),page_up(PageUp),scroll_lock(ScrlLock), pause(PauseBreak) # ,print_screen(PrintScr.)f1=12(F1=12),menu(menu),num_lock(NumLock) 2.2.class Controller: 向系统发送键盘事件的控制器 # press(key): 按下某个键 # key: 按下的键 # release(key): 释放某个键 # pressed(*args): 使下边的按键均同时按下此键(可以用with打开) # type(str): 将字符串发送 2.3.class Listener: 键盘的监听器 Listener(on_press, on_release): 创建一个监听器 on_press: #按下某个键时调用的方法(参数为key) on_release: #释放某个键时调用的方法(参数为key) # 方法: run(): #启动监听器 stop(): #停止监听器 wait(): #等待监听器就绪 join(): #启动并等待线程停止 ===============================================================================
3.样本实例 3.1.控制键盘 # 使用pynput.keyboard.Controller: from pynput.keyboard import Key, Controller keyboard = Controller() # Press and release space keyboard.press(Key.space) keyboard.release(Key.space) # Type a lower case A; this will work even if no key on the # physical keyboard is labelled 'A' keyboard.press('a') keyboard.release('a') # Type two upper case As keyboard.press('A') keyboard.release('A') with keyboard.pressed(Key.shift): keyboard.press('a') keyboard.release('a') # Type 'Hello World' using the shortcut type method keyboard.type('Hello World') 3.2.监控键盘 # 使用pynput.keyboard.Listener这样: from pynput import keyboard def on_press(key): try: print('alphanumeric key {0} pressed'.format( key.char)) except AttributeError: print('special key {0} pressed'.format( key)) def on_release(key): print('{0} released'.format( key)) if key == keyboard.Key.esc: # Stop listener return False # Collect events until released with keyboard.Listener( on_press=on_press, on_release=on_release) as listener: listener.join() 3.3.标准鼠标监控 from pynput import mouse def on_move(x, y): print('Pointer moved to {0}'.format((x, y))) def on_click(x, y, button, pressed): print('{0} at {1}'.format( 'Pressed' if pressed else 'Released',(x, y))) if not pressed: # Stop listener return False def on_scroll(x, y, dx, dy): print('Scrolled {0} at {1}'.format( 'down' if dy < 0 else 'up',(x, y))) # Collect events until released with mouse.Listener(on_move=on_move,on_click=on_click, on_scroll=on_scroll) as listener: listener.join() ===============================================================================
4.应用 4.1.键盘监听-写入日志文件 from pynput.keyboard import Listener import logging filepath = "C:\\hi\\" logging.basicConfig(filename=(filepath+"keyboardmouselog.txt"), format="%(asctime)s:%(message)s",level=logging.DEBUG) print('ascii=',"%(asctime)s:%(message)s") def press(key): logging.info(key) with Listener(on_press = press) as listener: listener.join() 说明: # 其中 % (asctime) # s表示时间, % (message) # s表示用户输入,DEBUG是日志的级别,多用于调试。 ===============================================================================
4.2.鼠标监控封装类(暂停,启动,停止) from pynput import mouse,keyboard from collections import deque import threading,time,os,sys ''' 1.说明: 1.0.tcy shanghai 2018/8/28 测试平台windows7 python3.7 pycharm20182.1 1.1. 一个鼠标监听器是一个线程。所有的回调将从线程调用。 1.2. 任何地方调用pynput.mouse.Listener.stop,mouse.Listener.StopException 或从回调中返回False来停止监听器。 2.用途: 1.1.本函数主要用作鼠标监听 1.2.实现鼠标监听暂停,启动,停止;停止和销毁后不能再进行鼠标监听,暂停后可以恢复。 3.技术要点 1.1.构造2个event,停止和暂停;退出采用回调函数内部return False以恢复 ''' class MouseClass(threading.Thread): def __init__(self, *args, **kwargs): super(MouseClass, self).__init__(*args, **kwargs) self.mouse_listion=mouse.Listener() self.__mouse_pause_flag_=threading.Event() # 用于暂停鼠标线程的标识 self.__mouse_pause_flag_.set() # 鼠标线程不阻塞 self.__mouse_run_flag_ = threading.Event() # 用于停止鼠标线程的标识 self.__mouse_run_flag_.set() # 鼠标线程开始启用 self.__mouse_destroy_flag_=True #True鼠标监听不退出 def on_move(self,x, y ): print("Pointer moved to {0} {1}".format((x,y),time.ctime())) if not self.__mouse_destroy_flag_: #false鼠标监听停止 return False #注意:不要返回True,否则不能够暂停等功能 def on_click(self,x, y , button, pressed): print('{0}at{1} '.format('Pressed' if pressed else 'Released',(x, y))) #凸轮键松开鼠标监控停止 if (not self.__mouse_destroy_flag_) or (not pressed):#false鼠标监听停 return False def on_scroll(self,x, y ,dx, dy): print('Scrolled{0} at {1}'.format( 'down' if dy < 0 else 'up',(x, y))) if not self.__mouse_destroy_flag_: #false鼠标监听停止 return False def run(self): while self.__mouse_run_flag_.is_set() : if not self.__mouse_destroy_flag_: break self.__mouse_pause_flag_.wait() with mouse.Listener( no_move = self.on_move, on_click = self.on_click,on_scroll = self.on_scroll) as listener: self.mouse_listion = listener self.mouse_listion.join() def mouse_pause(self): self.__mouse_pause_flag_.clear() # 为False鼠标线程阻塞,暂停鼠标功能 print('鼠标暂停...;当前线程==>%s ;线程数量==%d\n' % ( threading.current_thread().name, threading.activeCount())) def mouse_resume(self): self.__mouse_pause_flag_.set() # True鼠标线程停止阻塞,开启鼠标功能 print('鼠标恢复...;当前线程==>%s ;线程数量==%d\n' % ( threading.current_thread().name, threading.activeCount())) def mouse_stop(self): self.__mouse_run_flag_.clear() # 设置为False鼠标线程停止 self.__mouse_pause_flag_.set() print('鼠标停用...;当前线程==>%s ;线程数量==%d\n' %( threading.current_thread().name, threading.activeCount())) def mouse_destroy(self): self.__mouse_destroy_flag_=False # 鼠标监听停止 print('鼠标监听停止;当前线程==>%s ;线程数量==%d\n' %( threading.current_thread().name, threading.activeCount())) #测试函数 def mouse_test(): km=MouseClass() print('1.Start runing...') km.start() time.sleep(5) print('2.Mouse pause...') km.mouse_pause() time.sleep(5) print('3.Mouse start....') km.mouse_resume() time.sleep(5) print('4.Mouse stop....') # km.mouse_stop()#任选一个停止 km.mouse_destroy()#任选一个停止 time.sleep(5) print('5.End all program!') print('当前线程==>%s ;线程数量==%d\n' %( threading.current_thread().name, threading.activeCount())) mouse_test() # 结果输出: # 说明:输出结果视你按下鼠标的什么键 ''''''''' 1.Start runing... Pressed at (338, 619) Released at (338, 619) Scrolled down at (338, 619) Scrolled down at (338, 620) 2.Mouse pause... 鼠标暂停...;当前线程==>MainThread ;线程数量==3 ... 3.Mouse start.... 鼠标恢复...;当前线程==>MainThread ;线程数量==2 ... 4.Mouse stop.... 鼠标监听停止;当前线程==>MainThread ;线程数量==3 ... 5.End all program! 当前线程==>MainThread ;线程数量==1 ''''''''' =============================================================================== 4.3.鼠标监控封装类(暂停,启动,停止)-线程挂起 from pynput import mouse,keyboard from collections import deque import threading,time,os,sys ''' 1.说明: 1.0.tcy shanghai 2018/8/28 测试平台windows7 python3.7 pycharm20182.1 1.1. 一个鼠标监听器是一个线程。所有的回调将从线程调用。 1.2. 任何地方调用pynput.mouse.Listener.stop,mouse.Listener.StopException 或从回调中返回False来停止监听器。 2.用途: 1.1.本函数主要用作鼠标监听 1.2.实现鼠标监听暂停启动停止;停止和销毁后不能再进行鼠标监听,暂停后可 3.技术要点 1.1.采用鼠标监听内部的线程挂起,当暂停时鼠标不起左右,恢复后又正常工作。 ''' class MouseClass(threading.Thread): def __init__(self, *args, **kwargs): super(MouseClass, self).__init__(*args, **kwargs) self.mouse_listion=mouse.Listener() self.__mouse_run_flag_=True # 用于暂停鼠标线程不挂起 self.__mouse_destroy_flag_=True #True鼠标监听不退出 def on_move(self,x, y ): print("Pointer moved to {0} {1}".format((x,y),time.ctime())) if not self.__mouse_destroy_flag_: #false鼠标监听停止 return False # 注意:不要返回True,否则不能够暂停等功能 def on_click(self,x, y , button, pressed): print('{0} at{1}'.format('Pressed' if pressed else 'Released',(x, y))) #凸轮键松开鼠标监控停止 if (not self.__mouse_destroy_flag_) or (not pressed): #false鼠标监听停 return False def on_scroll(self,x, y ,dx, dy): print('Scrolled {0} at {1}'.format( 'down' if dy <0 else 'up',(x, y))) if not self.__mouse_destroy_flag_: #false鼠标监听停止 return False def run(self): while 1: with mouse.Listener(no_move = self.on_move,on_click = self.on_click, on_scroll = self.on_scroll, suppress=not self.__mouse_run_flag_) as self.mouse_listion: self.mouse_listion.join() if not self.__mouse_destroy_flag_: break def mouse_pause(self): self.__mouse_run_flag_ = False print('鼠标暂停...;当前线程==>%s ;线程数量==%d\n' % ( threading.current_thread().name, threading.activeCount())) def mouse_resume(self): self.__mouse_run_flag_=True print('鼠标恢复...;当前线程==>%s ;线程数量==%d\n' % ( threading.current_thread().name, threading.activeCount())) def mouse_destroy(self): self.__mouse_destroy_flag_=False # 鼠标监听停止 self.__mouse_run_flag_ = True print('鼠标监听停止;当前线程==>%s ;线程数量==%d\n' %( threading.current_thread().name, threading.activeCount())) #测试函数 def mouse_test(): km=MouseClass() print('1.Start runing...') km.start() time.sleep(5) print('2.Mouse pause...') km.mouse_pause() time.sleep(5) print('3.Mouse start....') km.mouse_resume() time.sleep(5) print('4.Mouse stop....') km.mouse_destroy()#任选一个停止 time.sleep(5) print('5.End all program!') print('当前线程==>%s ;线程数量==%d\n' %( threading.current_thread().name, threading.activeCount())) mouse_test() #输出结果: # 1.Start runing... # Pressed at (321, 553) # Released at (321, 553) # Scrolled down at (321, 553) # Scrolled down at (320, 556) # Scrolled down at (320, 556) # 2.Mouse pause... # 鼠标暂停...;当前线程==>MainThread ;线程数量==3 '''此时鼠标不起作用''' # Scrolled down at (320, 556) # Scrolled down at (320, 556) # Pressed at (320, 556) # Released at (320, 556) # Scrolled down at (320, 556) # Scrolled down at (320, 556) '''估计是将队列中的剩余任务输出;参考原函数定义''' # 3.Mouse start.... # 鼠标恢复...;当前线程==>MainThread ;线程数量==3 '''此时鼠标起作用''' # Pressed at (320, 556) # Released at (320, 556) # Scrolled down at (320, 556) # 4.Mouse stop.... # 鼠标监听停止;当前线程==>MainThread ;线程数量==3 # Scrolled down at (320, 556) '''将队列中的剩余任务输出;鼠标监听退出,等待主线程完成''' # 5.End all program! # 当前线程==>MainThread ;线程数量==1 ------------------------------------------------------------------------------- ''' 技术要点 1.1.采用 self.mouse_listion.stop()暂停监听 等价于self.mouse_listion.StopException 1.2.最好不要用self.mouse_listion.run(),测试出现一些异常; ''' 样例: class MouseClass(threading.Thread): def run(self): while 1: with mouse.Listener( no_move = self.on_move,on_click =self.on_click, on_scroll = self.on_scroll) as self.mouse_listion: if self.__mouse_run_flag_: self.mouse_listion.join() else: self.mouse_listion.stop() # 暂停监听等价于下条语句 # self.mouse_listion.StopException # 暂停监听等价于上条语句 if not self.__mouse_destroy_flag_: break =============================================================================== 4.4.键盘监听(字符,汉字) - 函数实现 #你能在键盘监听运行期间输入键代码,如‘a',或者汉字 """ 1.作者:tcy 写于上海叶榭。2018/8/30 2.用途:实时监听键盘,可用来启停程序,键盘中断。 如输入stop停止事件,输入start开始运行。 3.平台:window7 python3.7 PyCharm模拟。 4.技术说明:用程序和类分别包装。建议用类 监听部分有暂停键盘监听,恢复监听,销毁监听; 暂停后可以恢复,但销毁后不能再恢复 """ from pynput import keyboard import threading,time listener=keyboard.Listener() run_flag=True pause_flag=True def on_press(key): key_char = key.char if isinstance(key, keyboard.KeyCode) else str(key) try: print('alphanumeric key {0} pressed'.format( key_char)) except AttributeError: print('special key {0} pressed'.format( key)) def on_release(key): global run_flag # print('{0} released'.format( # key)) # print('thread----------=',threading.activeCount(),threading.current_thread().name) if not run_flag:#key == keyboard.Key.esc: # Stop listener return False def keyboard_pause(listen=listener): global pause_flag listen.stop() pause_flag=False def keyboard_resume(listen=listener): global pause_flag pause_flag=True # listen.run() def keyboard_stop(listen=listener): global run_flag,pause_flag pause_flag=True run_flag=False def run(): global listener,run_flag,pause_flag while run_flag: with keyboard.Listener( on_press=on_press, on_release=on_release) as listener: if pause_flag: listener.join() t = threading.Thread(target=run) t.start() print('1.start run.....---------------------11--------------------') time.sleep(5) print('1.end run.....---------------------12--------------------') print('2.start pause.....-------------------21--------------------') keyboard_pause(listen=listener) time.sleep(5) print('2.end pause.....-------------------22--------------------') print('3.start run.....---------------------31-------------------') keyboard_resume() time.sleep(5) print('3.end run.....---------------------32-------------------') print('4.start stop.....----------------------41-----------------------------') keyboard_stop() time.sleep(1) print('4.end stop.....----------------------------42---------------------------') time.sleep(1) print('5.all end.....----------------------------5---------------------------') 输出结果: ''''''''' C:\python37\python.exe C:/Users/Administrator/PycharmProjects/test_qt/f7.py 1.start run.....---------------------11-------------------- salphanumeric key s pressed alphanumeric key Key.shift pressed alphanumeric key s pressed alphanumeric key Key.space pressed 是1.end run.....---------------------12-------------------- 2.start pause.....-------------------21-------------------- 是是 是2.end pause.....-------------------22-------------------- 3.start run.....---------------------31------------------- 的alphanumeric key Key.space pressed alphanumeric key d pressed alphanumeric key Key.space pressed 的alphanumeric key d pressed alphanumeric key Key.space pressed 的alphanumeric key d pressed 的alphanumeric key Key.space pressed alphanumeric key d pressed 3.end run.....---------------------32------------------- 4.start stop.....----------------------41----------------------------- 的alphanumeric key Key.space pressed 4.end stop.....----------------------------42--------------------------- 的5.all end.....----------------------------5--------------------------- Process finished with exit code 0 ''' =============================================================================== 4.5.键盘监听(字符,汉字)- 类实现 from pynput import keyboard from collections import deque import threading,time #处理字符串类 class KeyboardStr(): ''' 1.接收键盘监听取得的字符串,处理带有shift切换的键,如输入!,大写字符; 2.要取得可打印的字符串,默认数量最多10个,用t.a.get_print_chars获取; 3.t.a.get_print_chars获取最多100个任意字符和非打印字符(以代码命名) ''' def __init__(self): # super(KeyboardStr, self).__init__() # 获取字符串变量 self.shift_press_flag=False self.get_print_chars = deque() # 获取键盘字符串以回车结束 self.get_all_chars = deque() # 获取键盘所有字符串,含非打印字符以回车结束 self.__get_print_chars = deque() self.__get_all_chars = deque() self.__shift_up_chars = { '0': ')', '1': '!', '2': '@', '3': '#', '4': '$', '5': '%', '6': '^', '7': '&', '8': '*', '9': '(', '10': '_', '11': '+', '12': '~', '13': '{', '14': '}', '15': ':', '16': '"', '17': '|', '18': '<', '19': '>', '20': '?'} self.__shift_down_key_chars = { "0": "0", "1": "1", "2": "2", "3": "3", "4": "4", "5": "5", "6": "6", "7": "7", "8": "8", "9": "9", "10": "-", "11": "=", "12": "`", "13": "[", "14": "]", "15": ";", "16": "'", "17": "'\'", "18": ",", "19": ".", "20": "/"} # 处理键盘上下键 大小写问题 def __get_combination_key_char(self,key_char:str): new_char='' is_up_down_key_char = key_char in self.__shift_down_key_chars.values() if key_char.__len__()==1: if key_char.isalpha() and self.shift_press_flag: new_char=key_char.upper() elif is_up_down_key_char and self.shift_press_flag: index_name = [k for k, v in self.__shift_down_key_chars.items() if v == key_char] new_char=self.__shift_up_chars[index_name[0]] else: new_char=key_char return new_char else: return None '''获取回车确认前10个可打印键盘字符;回车后显示;''' def GetPrintChars(self, key_char:str,GetstrNumber=10): if key_char.__len__()==1: new_char = self.__get_combination_key_char(key_char) self.__get_print_chars.append(new_char) while self.__get_print_chars.__len__() > GetstrNumber: self.__get_print_chars.popleft() if key_char=='Key.enter': self.get_print_chars = self.__get_print_chars.copy() self.__get_print_chars.clear() print('GetPrintCharStr===>%s\n' % self.get_print_chars) '''获取回车确认前100个所有字符,含非打印字符''' def GetAllChars(self, key_char, GetstrNumber=100): self.__get_all_chars.append(key_char) while self.__get_all_chars.__len__() > GetstrNumber: self.__get_all_chars.popleft() if key_char == 'Key.enter': self.get_all_chars = self.__get_all_chars.copy() self.__get_all_chars.clear() print('GetAllCharStr===>%s\n' % self.get_all_chars) #******************************************************************************** class KeyboardClass(threading.Thread,KeyboardStr): '''1.用途:实时监听键盘事件,能暂停,恢复,销毁。 2.测试:测试部分有2个,一个测试键盘监听,一个测试字符串处理。''' def __init__(self): super(KeyboardClass, self).__init__() KeyboardStr.__init__(self) #键盘监听变量 self.run_flag = True self.pause_flag = True self.listener = keyboard.Listener() self.a=KeyboardStr() def __GetOneChar(self, key): return key.char if isinstance(key, keyboard.KeyCode) else str(key) def on_press(self,key): key_char = self.__GetOneChar(key) try: if key_char=='Key.shift': self.a.shift_press_flag=True # print('alphanumeric key {0} pressed'.format(key_char)) except AttributeError: key_char=None print('special key {0} pressed'.format(key_char)) finally: print('Alphanumeric key = 【{0}】 pressed...'.format(key_char)) def on_release(self,key): key_char = self.__GetOneChar(key) if key_char == 'Key.shift': self.a.shift_press_flag = False self.a.GetPrintChars(key_char) self.a.GetAllChars(key_char) # print('{0} released'.format(key)) if not self.run_flag:#key == keyboard.Key.esc: return False# Stop listener def keyboard_pause(self): self.listener.stop() self.pause_flag=False def keyboard_resume(self): self.pause_flag=True def keyboard_destroy(self): self.pause_flag=True self.run_flag=False self.listener.stop() def run(self): while self.run_flag: with keyboard.Listener(on_press=self.on_press, on_release=self.on_release) as self.listener: if self.pause_flag: self.listener.join() #键盘字符处理测试程序 def test_str(): t=KeyboardClass() t.start() print('1.start run...................................') while 1: print('2.可打印字符串===》',t.a.get_print_chars) print('3.所有字符串===》',t.a.get_all_chars) time.sleep(2) #键盘监听测试程序 def test_keyboard_listen(): t = KeyboardClass() t.start() print('1.1.start run...................................',time.ctime()) time.sleep(5) print('1.2.start run stop..............................', time.ctime()) print('2.1.start pause..................................', time.ctime()) t.keyboard_pause() time.sleep(5) print('2.2.end pause.....................................%s\n'% (time.ctime())) print('3.1.keyboard listener resume......................%s\n'% (time.ctime())) t.keyboard_resume() time.sleep(5) print('3.2.stop resume.stoping.............................%s\n'% (time.ctime())) print('4.1.start destroy...................................%s\n'% (time.ctime())) t.keyboard_destroy() time.sleep(1) print('4.2.end destroy......................................%s\n'%( time.ctime())) time.sleep(1) print('5.all program end.exit....') # test_str() test_keyboard_listen() #------------------------------------------------------------------------------------------------------- #第一步分测试显示如下:随机显示内容,视你的按下什么键 ''''''''' 1.1.start run................................... Mon Nov 12 19:43:03 2018 Alphanumeric key = 【d】 pressed... 的Alphanumeric key = 【Key.space】 pressed... Alphanumeric key = 【d】 pressed... Alphanumeric key = 【Key.space】 pressed... 的Alphanumeric key = 【d】 pressed... Alphanumeric key = 【g】 pressed... 1.2.start run stop.............................. Mon Nov 12 19:43:08 2018 2.1.start pause.................................. Mon Nov 12 19:43:08 2018 递归的2.2.end pause.....................................Mon Nov 12 19:43:13 2018 3.1.keyboard listener resume......................Mon Nov 12 19:43:13 2018 3.2.stop resume.stoping.............................Mon Nov 12 19:43:18 2018 4.1.start destroy...................................Mon Nov 12 19:43:18 2018 4.2.end destroy......................................Mon Nov 12 19:43:19 2018 个5.all program end.exit.... Process finished with exit code 0 ''' ===============================================================================