多线程鼠标位置记录脚本运行异常求助及点击宏录制回放脚本分享
问题分析与修复方案
看起来你在多线程/进程的阻塞逻辑和数据共享上踩了坑,咱们一步步来解决你的核心问题,再聊聊优化方向。
第一个脚本的致命问题:进程阻塞导致键盘监听器从未启动
你当前的代码里,p1.join()会完全阻塞主进程,直到子进程p1结束——但func1是个死循环,永远不会停止,所以主进程根本没机会执行到后面的键盘监听器代码,自然看不到任何输出,进程会一直挂着。
另外还有个隐藏问题:多进程之间的全局变量是独立的,子进程里的mouse_positions是主进程的拷贝,就算监听器能启动,主进程也拿不到子进程记录的鼠标位置。
修正后的代码(用线程实现,更适合场景)
因为你的需求是共享数据(记录的鼠标位置),用线程比进程更简单,线程共享同一内存空间,无需额外处理就能访问共享变量:
from pynput.keyboard import Listener import pyautogui import threading import time mouse_positions = [] stop_thread = False def record_mouse(): global stop_thread while not stop_thread: time.sleep(2) mouse_positions.append(pyautogui.position()) # 可选:实时打印记录的位置,方便调试 # print(f"记录鼠标位置:{pyautogui.position()}") def on_press(key): global stop_thread if "q" in str(key): print('q was pressed!') stop_thread = True # 通知鼠标记录线程停止循环 # 打印所有记录的鼠标位置 print("\n=== 记录的鼠标位置 ===") for count, pos in enumerate(mouse_positions, 1): print(f"第{count}次(间隔2秒):X={pos[0]}, Y={pos[1]}") return False # 返回False终止键盘监听器 # 可选:打印其他按键输入,方便调试 print(f"按下按键:{key}") if __name__ == '__main__': # 启动鼠标记录线程 mouse_thread = threading.Thread(target=record_mouse) mouse_thread.start() # 启动键盘监听器,这里的join会阻塞主进程直到监听器终止 with Listener(on_press=on_press) as listener: listener.join() # 等待鼠标线程完全退出 mouse_thread.join()
关键修改点说明
- 替换
multiprocessing.Process为threading.Thread:解决数据共享问题,线程能直接读写全局的mouse_positions - 移除了阻塞主进程的
p1.join():先启动线程,再启动键盘监听器,让监听器的join()保持主进程运行 - 添加
stop_thread标志:优雅终止鼠标记录线程,避免强制杀死进程 - 替换
exit()为return False:exit()会直接终止整个程序,来不及打印鼠标位置;返回False会正常终止监听器,再处理后续逻辑
分享的点击宏脚本(功能完善版)
感谢你分享的这款记录鼠标点击并回放的脚本,功能很实用,这里整理成更易读的格式并做了小优化:
from pynput.keyboard import Listener import pyautogui from pynput import mouse import time both_pos = [] pressed_key = None def on_click(x, y, button, pressed): if pressed: if pressed_key == "1": both_pos.append(x) both_pos.append(y) print(f"记录点击位置:({x}, {y})") else: pass if pressed_key == 'q': return False def on_press(key): print("\n操作说明:按'1'切换记录状态,按'q'回放操作,按'esc'退出程序") global pressed_key key_str = str(key) if 'Key.esc' in key_str: return False if '1' in key_str: # 切换记录状态:如果当前是记录状态则关闭,否则开启 pressed_key = None if pressed_key == '1' else '1' status = "开启" if pressed_key == '1' else "关闭" print(f"记录状态已{status}") if 'q' in key_str: print("开始回放操作...") print(f"共记录了{len(both_pos)//2}次点击") for point in range(0, len(both_pos), 2): time.sleep(3) x = both_pos[point] y = both_pos[point+1] print(f"点击位置:({x}, {y})") pyautogui.click(x=x, y=y) print("点击完成") return False # 启动鼠标监听器 mouse_listener = mouse.Listener(on_click=on_click) mouse_listener.start() # 启动键盘监听器 with Listener(on_press=on_press) as listener: listener.join()
小优化说明
我给这个脚本加了更清晰的状态提示,调整了位置存储逻辑(直接存数值而非字符串,避免后续转int的麻烦),使用起来更直观。
内容的提问来源于stack exchange,提问作者Oyosied
相关产品推荐
相关产品推荐

