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
相关产品推荐
相关产品推荐

