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

如何在main.py中同时运行两个含无限循环的Python监听脚本?

解决Python多监听器阻塞问题:同时运行键盘和鼠标监听

这问题太常见了!你之所以只能运行第一个脚本,核心原因是listener.join()是阻塞式调用——它会暂停当前线程,直到监听器停止运行。而你的监听器是无限循环的(除非手动干预),所以第一个监听器的join()永远不会结束,程序根本没机会执行第二个监听器的代码。

解决思路:用多线程让两个监听器并行运行

我们需要把每个监听器的逻辑封装成独立函数,然后在主线程中用线程分别启动它们。这样两个阻塞的join()就会在各自的线程里运行,不会互相卡住。

步骤1:修改你的监听脚本,封装成函数

原来的脚本直接在模块级别执行了listener.join(),导致import时就会阻塞。我们把监听逻辑封装成可调用的函数:

修改后的keyboard_listener.py:

from pynput.keyboard import Key, Listener

def start_keyboard_listener():
    def on_press(key):
        print(f"Pressed key: {key}")
    
    with Listener(on_press=on_press) as listener:
        listener.join()

修改后的mouse_listener.py:

from pynput.mouse import Listener

def start_mouse_listener():
    def on_click(x, y, button, pressed):
        print(f"Mouse button: {button}, Pressed: {pressed}")
    
    with Listener(on_click=on_click) as listener:
        listener.join()

步骤2:在main.py中用线程启动两个监听器

使用Python内置的threading模块,创建两个线程分别运行两个监听器函数:

import threading
from keyboard_listener import start_keyboard_listener
from mouse_listener import start_mouse_listener

if __name__ == "__main__":
    # 创建线程对象,指定要运行的目标函数
    keyboard_thread = threading.Thread(target=start_keyboard_listener)
    mouse_thread = threading.Thread(target=start_mouse_listener)
    
    # 启动两个线程
    keyboard_thread.start()
    mouse_thread.start()
    
    # 必须添加这两行:让主线程等待子线程结束
    # 如果不写,主线程会直接退出,导致两个监听线程也跟着终止
    keyboard_thread.join()
    mouse_thread.join()

为什么这样能行?

每个线程都是独立的执行流,start()会启动线程并运行目标函数,而join()会让主线程等待子线程完成。这样两个监听器的阻塞逻辑分别在各自的线程里运行,就能同时监听键盘和鼠标事件了。

额外提示:优雅停止监听器

如果需要手动停止监听器,可以在回调函数里添加停止条件,比如按下ESC键时退出:

# 在键盘监听的on_press函数中添加:
def on_press(key):
    print(f"Pressed key: {key}")
    if key == Key.esc:
        # 返回False会触发监听器停止
        return False

这样按下ESC键就能停止键盘监听器,对应的线程也会自动结束。

内容的提问来源于stack exchange,提问作者Saeed Shafiee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:40:37