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

使用multiprocessing时触发EOFError: Ran out of Input错误如何解决?

问题原因排查

直接触发EOFError: Ran out of Input的核心原因

  • 你运行代码的系统大概率是Windows,Python的multiprocessing模块在Windows下默认使用spawn模式启动子进程:子进程会重新导入整个主模块,同时需要把Process传入的target、参数全部通过pickle序列化后传给子进程,序列化失败或者子进程读取序列化数据异常就会触发这个报错。
  • 你在死循环里每次处理帧都新建一个Process实例,高频创建销毁进程的开销极高,且每次都要序列化帧、obd实例对象:你的obd实例里包含YOLO模型、加载的权重等无法被pickle序列化的资源,序列化直接失败就会报EOF错误。

代码里的其他致命逻辑错误

  • Process.start()方法没有返回值,你写的frame=Process(target=obd.predictYolo, args=(frame,)).start()会直接把frame赋值为None,后续传给showFrames的就是空值,哪怕没有多进程报错也无法正常展示。
  • 你的多进程没有做生命周期管理:既没有join回收子进程资源,也没有控制并发数量,运行几秒后进程数就会爆炸,直接占满系统资源。
  • 你直接把类实例方法obd.predictYolo作为子进程target,multiprocessing会尝试序列化整个obd实例传到子进程,哪怕你没有显式传实例作为参数也会触发序列化逻辑。
修复方案

调整架构思路

不要每次处理帧都新建进程,全局只启动1个(或固定数量)检测子进程,用multiprocessing.Queue在主进程和检测进程之间传递原始帧、处理后的帧,完全避免频繁创建进程和不可序列化对象的传递。

修复后示例代码

from multiprocessing import Process, Queue
import sys
import cv2
from typing import Union
from threading import Thread

import videoPlayerThreading as vpt

# 检测逻辑改成顶层函数,在子进程内部初始化模型,避免序列化
def detection_worker(input_q: Queue, output_q: Queue):
    from objDect import objDect as od
    # 模型在子进程里初始化,不用序列化传到子进程
    obd = od(videoSources=0)
    while True:
        frame = input_q.get()
        if frame is None:
            # 收到结束信号退出
            break
        processed_frame = obd.predictYolo(frame)
        output_q.put(processed_frame)

def main(videoSource):
    # 初始化队列,设置最大长度避免帧堆积
    input_q = Queue(maxsize=2)
    output_q = Queue(maxsize=2)
    # 全局只启动一个检测进程
    det_process = Process(target=detection_worker, args=(input_q, output_q))
    det_process.start()

    getFrame = vpt.getFrames(videoSource).start()
    showFrame = vpt.showFrames(videoSource).start()

    while True:
        if not getFrame.doVideo or not showFrame.doVideo:
            # 发结束信号给检测进程
            input_q.put(None)
            det_process.join()
            getFrame.stop()
            showFrame.stop()
            cv2.destroyAllWindows()
            sys.exit()
        # 读原始帧
        raw_frame = getFrame.frame
        if raw_frame is None:
            continue
        # 队列没满就送帧去检测
        if not input_q.full():
            input_q.put(raw_frame)
        # 有处理完的帧就取出来展示
        if not output_q.empty():
            showFrame.frame = output_q.get()

if __name__=="__main__":
   main(0)

额外优化建议

  • 你现有的getFrames和showFrames类没有做线程安全的读写锁,多线程同时读写self.frame可能会出现半帧、花屏的问题,建议给frame的读写加threading.Lock锁。
  • 队列设置合理的最大长度,避免处理速度跟不上读帧速度导致内存暴涨。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 14:57:04