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

Python TypeError排查:摄像头运行数小时报'NoneType'不可下标

问题原因与解决方案

报错根源

报错TypeError: 'NoneType' object is not subscriptable是因为长时间运行后,cap.read()返回的frame变为None——这意味着摄像头出现了读取失败的情况,可能是硬件连接松动、系统资源耗尽、摄像头自动休眠等原因导致的。

修复方案

1. 新增读取有效性检查

在使用frame之前,必须先判断cap.read()的返回值ret是否为True,若读取失败则重新初始化摄像头或跳过当前循环。

2. 修复代码中的隐性问题

  • decoder函数里错误使用了全局变量frame,应改为使用传入的image参数
  • wyslijEmail函数缺少ssl和smtplib的导入,会导致邮件发送功能失效

3. 优化资源管理

定期释放并重新获取摄像头资源,避免长时间运行引发的资源泄漏。

修正后的完整代码

import cv2
import numpy as np
import ssl
import smtplib
from pyzbar.pyzbar import decode
from gpiozero import Buzzer
from time import sleep

qr = "1"
ean = "1"
a = 0

def wyslijEmail(tresc):
    port = 465  # For SSL
    smtp_server = "smtp.gmail.com"
    sender_email = "***"  # 替换为你的邮箱地址
    receiver_email = "***"  # 替换为收件人邮箱地址
    password = "***"  # 替换为邮箱密码/应用专用密码
    
    context = ssl.create_default_context()
    with smtplib.SMTP_SSL(smtp_server, port, context=context) as server:
        server.login(sender_email, password)
        server.sendmail(sender_email, receiver_email, tresc)

def decoder(image):
    global a
    global qr
    global ean
    buzzer = Buzzer(14)
    kodQR = "QR"
    ean13 = "EAN"
    
    gray_img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    barcode = decode(gray_img)

    for obj in barcode:
        points = obj.polygon
        (x,y,w,h) = obj.rect
        pts = np.array(points, np.int32)
        pts = pts.reshape((-1, 1, 2))
        cv2.polylines(image, [pts], True, (0, 255, 0), 3)

        barcodeData = obj.data.decode("utf-8")
        barcodeType = obj.type
        
        if kodQR in barcodeType:
            print("qr")
            if qr != str(barcodeData):
                qr = str(barcodeData)
                wyslijEmail(barcodeData)
                print("wysylam @")
                buzzer.on()
                sleep(1)
                buzzer.off()
                sleep(1)
            else:
                print("重复的QR码")
        elif ean13 in barcodeType:
            print("ean")
            if ean != str(barcodeData):
                ean = str(barcodeData)
                wyslijEmail(barcodeData)
                print("wysylam @")
                buzzer.on()
                sleep(1)
                buzzer.off()
                sleep(1)
            else:
                print("重复的EAN码")
            
        string = f"Data {barcodeData} | Type {barcodeType}"
        cv2.putText(image, string, (x,y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,0,0), 2)
        print(f"Barcode: {barcodeData} | Type: {barcodeType}")
        print(a)
        a += 1

def init_camera():
    cap = cv2.VideoCapture(0)
    cap.set(3, 2592)
    cap.set(4, 1944)
    return cap

cap = init_camera()

while True:
    ret, frame = cap.read()
    # 检查摄像头读取是否成功
    if not ret or frame is None:
        print("摄像头读取失败,重新初始化...")
        cap.release()
        cap = init_camera()
        sleep(2)
        continue
    
    try:
        sky = frame[800:1200, 330:1500]
        decoder(sky)
        cv2.imshow('Image', sky)
    except Exception as e:
        print(f"处理帧时出错: {e}")
        sleep(1)
    
    code = cv2.waitKey(10)
    if code == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

关键优化点说明

  • 摄像头容错机制:每次读取帧后验证有效性,失败时自动重新初始化摄像头,彻底避免None切片报错
  • 变量作用域修复:将decoder函数中操作的frame改为传入的image参数,消除全局变量依赖
  • 异常捕获:添加帧处理的异常捕获,避免单次错误导致整个程序崩溃
  • 补充缺失依赖:添加ssl和smtplib导入,确保邮件发送功能正常运行

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 04:35:28