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

Python threading中self.running标识控制双目相机线程启停异常问题

问题根因

Python标准库的Thread实例仅允许调用一次start()方法,一旦run()方法执行完成,线程就会永久终止,仅修改self.running标志无法重新唤醒已经退出的线程。你遇到的两个现象具体原因如下:

  • 初始self.running = True:首次启动线程后run()方法正常执行采集逻辑,按下停止键将self.running设为False后,while循环退出、run()方法执行完毕,线程终止。后续按下启动键仅修改了标志位,没有重新启动新的线程,因此没有反应。
  • 初始self.running = None:while判断逻辑中None等价于假,若你没有修改run()中的循环条件,线程启动后会直接退出;如果你自行修改了循环条件为while self.running is not None,则将self.running设为False不会触发循环退出,因此无法终止线程。

修复方案

推荐采用「线程常驻+标志位控制采集状态」的方案,避免反复创建销毁线程、开关相机设备带来的性能开销,修改逻辑如下:

  1. 将run()方法拆分为两层循环:外层维持线程存活,内层仅在采集标志为真时执行读帧、渲染逻辑
  2. 停止采集时仅退出内层循环,不终止外层循环
  3. 新增资源释放逻辑,程序退出时主动释放相机、销毁OpenCV窗口

可运行修改后代码

from threading import Thread
import time
import cv2
import keyboard

class LeftFrame(Thread):
    def __init__(self):
        super().__init__()
        self.daemon = True  # 设为守护线程,主程序退出时自动销毁
        self.running = False  # 采集控制标志
        self.thread_alive = True  # 线程存活控制标志

    def run(self):
        cap = cv2.VideoCapture(0)
        # 外层循环维持线程存活
        while self.thread_alive:
            # 内层循环仅在running为True时执行采集
            while self.running:
                success, img = cap.read()
                if not success:
                    break
                cv2.imshow("left_cam", img)
                cv2.waitKey(1)
            # 停止采集时短暂休眠降低CPU占用
            time.sleep(0.01)
        # 线程退出前释放相机
        cap.release()
        cv2.destroyWindow("left_cam")

    def stop_capture(self):
        self.running = False

    def start_capture(self):
        self.running = True

    def terminate_thread(self):
        self.running = False
        self.thread_alive = False

# 初始化并启动常驻线程
left_cam_thread = LeftFrame()
left_cam_thread.start()

if __name__ == "__main__":
    while True:
        # 按f停止采集
        if keyboard.is_pressed('f'):
            left_cam_thread.stop_capture()
            time.sleep(1)
        # 按s启动采集
        if keyboard.is_pressed('s'):
            left_cam_thread.start_capture()
            time.sleep(1)
        # 按q退出整个程序
        if keyboard.is_pressed('q'):
            left_cam_thread.terminate_thread()
            left_cam_thread.join()
            cv2.destroyAllWindows()
            break

双目适配提示

右相机线程可以复用上述类逻辑,仅修改相机ID和窗口名称即可,两个线程相互独立不会互相干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 05:27:03