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

使用mss库结合多线程时出现AttributeError问题求助

多线程图像检测中MSS库的AttributeError问题修复

错误信息

Traceback (most recent call last):
  File "AppData\Local\Programs\Python\Python311\Lib\threading.py", line 1038, in _bootstrap_inner
    self.run()
  File "AppData\Local\Programs\Python\Python311\Lib\threading.py", line 975, in run
    self._target(*self._args, **self._kwargs)
  File "e:\Dev\CV3\vision.py", line 19, in image_tracker
    img = np.asarray(self.stc.grab(coordinates))
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\Dev\CV3\venv\Lib\site-packages\mss\base.py", line 90, in grab
    screenshot = self._grab_impl(monitor)
                 ^^^^^^^^^^^^^^^^^^^^^^^^
  File "E:\Dev\CV3\venv\Lib\site-packages\mss\windows.py", line 235, in _grab_impl
    srcdc, memdc = self._handles.srcdc, self._handles.memdc
                   ^^^^^^^^^^^^^^^^^^^
AttributeError: '_thread._local' object has no attribute 'srcdc'

原始代码

vision.py

import cv2
import mss
import numpy as np


class Vision:

stc = mss.mss()

def __init__(self, mon,):

    self.mon = self.stc.monitors[mon]

def image_tracker(self, top, left, width, height, window_name):

    coordinates = {'top': self.mon['top'] + top, 'left': self.mon['left'] + left, 'width': width, 'height': height}

    while True:
        img = np.asarray(self.stc.grab(coordinates))
        cv2.imshow(f'{window_name}', img)

        if cv2.waitKey(25) & 0xFF == ord('q'):
            cv2.destroyAllWindows()
            break

main.py

from vision import Vision
from threading import Thread


vision = Vision(2)

tensinon_line = Thread(target=vision.image_tracker, args=(1340, 870, 300, 25, 'Tension',))
counter = Thread(target=vision.image_tracker, args=(1300, 1385, 27, 20, 'Counter',))

tensinon_line.start()
counter.start()

问题原因

MSS的mss()实例不是线程安全的,你将它作为类的静态成员,导致多个线程共享同一个实例。MSS内部用_thread._local存储线程相关的句柄(如srcdc),新线程中没有初始化这些句柄,因此抛出属性不存在的错误。

修复方案

让每个线程使用独立的MSS实例,避免多线程共享同一个对象。修改vision.py如下:

import cv2
import mss
import numpy as np


class Vision:
    def __init__(self, mon):
        # 仅在初始化时获取监视器信息,不保留全局MSS实例
        with mss.mss() as stc:
            self.mon = stc.monitors[mon]

    def image_tracker(self, top, left, width, height, window_name):
        # 每个线程创建独立的MSS实例,用上下文管理器自动管理资源
        with mss.mss() as stc:
            coordinates = {
                'top': self.mon['top'] + top,
                'left': self.mon['left'] + left,
                'width': width,
                'height': height
            }
            while True:
                img = np.asarray(stc.grab(coordinates))
                cv2.imshow(window_name, img)
                if cv2.waitKey(25) & 0xFF == ord('q'):
                    cv2.destroyAllWindows()
                    break

说明

  • 初始化方法中临时创建MSS实例仅用于获取监视器参数,之后立即释放
  • 每个线程运行image_tracker时,都会创建专属的MSS实例,该实例会在当前线程中初始化所需的句柄资源,彻底避免多线程冲突

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 05:37:13