双线程启动异常:Flask服务与摄像头线程无法同时运行求助
问题修复方案
核心问题分析
你的代码里有几个关键错误导致线程无法同时运行:
- 线程创建方式错误:创建线程时用了
target=vd(),这会直接在主线程里执行vd函数,而不是把函数作为线程的执行目标。正确写法是target=vd(不带括号)。 - 摄像头线程被阻塞:
vd函数里启动Web线程后调用了th.join(),这会让摄像头线程一直等待Web线程结束,但Flask的app.run()是阻塞式的,摄像头循环根本没机会执行。 - Flask启动条件无效:
webWork里的if __name__ == "__main__":判断,在线程调用时不会触发,导致服务器无法启动。 - 帧数据格式错误:
gen_frames直接把OpenCV的帧对象拼接进响应,必须先编码成JPEG字节流才能返回。 - 多线程读写冲突:全局
frame被两个线程同时读写,需要加锁避免数据异常。
修复后的完整代码
#!/usr/bin/env python from datetime import datetime from flask import Flask, render_template, Response, request import numpy as np import cv2 from threading import Thread, Lock # Initialize the Flask app app = Flask(__name__) pwm_az = 0 pwm_tilt = 0 # 全局帧变量+锁 frame = None frame_lock = Lock() def vd(): global frame vid = cv2.VideoCapture(0) print("摄像头线程已启动") while True: ret, current_frame = vid.read() if not ret: break # 加锁更新全局帧 with frame_lock: frame = current_frame.copy() # 显示本地预览 cv2.imshow('frame', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break vid.release() cv2.destroyAllWindows() def gen_frames(): global frame while True: # 加锁读取全局帧 with frame_lock: if frame is None: continue # 将帧编码为JPEG字节流 ret, buffer = cv2.imencode('.jpg', frame) if not ret: continue frame_bytes = buffer.tobytes() yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n') @app.route('/') def index(): return render_template('index_2.html') @app.route('/video_feed') def video_feed(): return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame') def webWork(): # 去掉多余的判断,直接启动Flask app.run(host="localhost", port=8086, debug=False) # debug=True会重启线程,建议关闭 # 正确创建线程:传入函数引用,不带括号 thread_videoWork = Thread(target=vd, args=()) thread_webWork = Thread(target=webWork, args=()) # 启动两个线程 thread_videoWork.start() thread_webWork.start() # 等待线程结束(可选,避免主线程提前退出) thread_videoWork.join() thread_webWork.join()
关键修改说明
- 线程创建:把
target=vd()改成target=vd,确保函数在线程内执行,而非主线程提前执行。 - 移除阻塞逻辑:删掉
vd函数里启动Web线程和join()的代码,让摄像头线程专注于采集帧。 - Flask启动:去掉
webWork里的if __name__ == "__main__":判断,直接启动服务器;关闭debug=True,避免Flask debug模式自动重启线程导致重复启动。 - 帧编码:在
gen_frames里用cv2.imencode把OpenCV帧转成JPEG字节流,符合HTTP响应的格式要求。 - 线程锁:用
Lock()保护全局frame的读写操作,避免多线程同时操作导致的帧损坏或程序异常。
内容的提问来源于stack exchange,提问作者megaloldean
相关产品推荐
相关产品推荐

