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

如何在Python中通过按键立即终止含循环的多进程/线程程序?

解决按下P键立即终止Python程序的问题

问题根源

原代码存在两个导致关闭缓慢的核心问题:

  • Loop B是独立的子进程,Loop A线程仅自身break无法终止该进程
  • Loop B中的time.sleep(2)会让进程进入休眠状态,此时无法立即响应终止请求;另外pyautogui.locateOnScreen的检测过程也可能产生耗时延迟

方案1:强制终止进程(最快关闭)

通过保存子进程实例,按下P键时直接强制终止Loop B进程,再退出整个程序:

import keyboard
import time
import pyautogui
from multiprocessing import Process
from threading import Thread
import sys

# 全局保存Loop B的进程实例
loop_b_process = None

def loop_a():
    global loop_b_process
    while True:
        key = keyboard.read_key()
        if key == 'p':
            print('Program has stopped...')
            # 立即终止Loop B进程
            if loop_b_process and loop_b_process.is_alive():
                loop_b_process.terminate()
                loop_b_process.join()  # 等待进程彻底释放资源
            sys.exit()  # 退出整个程序
        else:
            print("Wrong key champ !")
            time.sleep(0.5)

def loop_b():
    while True:
        if pyautogui.locateOnScreen('image.png', confidence=0.5) is not None:
            print("I can see it")
        else:
            print("I am unable to see it")
        time.sleep(2)

if __name__ == '__main__':
    loop_b_process = Process(target=loop_b)
    loop_b_process.start()
    Thread(target=loop_a).start()

修改说明:

  • 全局变量loop_b_process让Loop A线程能直接访问并操作子进程
  • terminate()会强制终止Loop B进程,无视其当前执行状态,实现立即关闭
  • join()确保进程资源被彻底释放,避免残留
  • sys.exit()直接退出主程序,清除所有线程和进程

方案2:优雅终止进程(推荐)

如果不想强制终止进程,可通过multiprocessing.Event实现进程间通信,让Loop B主动检测终止信号:

import keyboard
import time
import pyautogui
from multiprocessing import Process, Event
from threading import Thread
import sys

# 进程间共享的终止事件
stop_event = Event()

def loop_a():
    while True:
        key = keyboard.read_key()
        if key == 'p':
            print('Program has stopped...')
            stop_event.set()  # 设置终止信号
            sys.exit()
        else:
            print("Wrong key champ !")
            time.sleep(0.5)

def loop_b():
    while not stop_event.is_set():
        if pyautogui.locateOnScreen('image.png', confidence=0.5) is not None:
            print("I can see it")
        else:
            print("I am unable to see it")
        # 用wait替代sleep,事件触发时立即唤醒
        stop_event.wait(2)

if __name__ == '__main__':
    loop_b_process = Process(target=loop_b)
    loop_b_process.start()
    Thread(target=loop_a).start()

修改说明:

  • stop_event是进程间共享的信号标记,Loop B每次循环都会检查其状态
  • stop_event.wait(2)替代time.sleep(2),当终止信号被设置时,进程会立即从等待状态唤醒,无需等到2秒结束
  • 这种方式让Loop B在当前循环结束后主动退出,既保证了响应速度,又避免了强制终止可能带来的资源泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 06:01:15