You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多线程鼠标位置记录脚本运行异常求助及点击宏录制回放脚本分享

问题分析与修复方案

看起来你在多线程/进程的阻塞逻辑和数据共享上踩了坑,咱们一步步来解决你的核心问题,再聊聊优化方向。

第一个脚本的致命问题:进程阻塞导致键盘监听器从未启动

你当前的代码里,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()

关键修改点说明

  1. 替换multiprocessing.Process为threading.Thread:解决数据共享问题,线程能直接读写全局的mouse_positions
  2. 移除了阻塞主进程的p1.join():先启动线程,再启动键盘监听器,让监听器的join()保持主进程运行
  3. 添加stop_thread标志:优雅终止鼠标记录线程,避免强制杀死进程
  4. 替换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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 12:02:47