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

Python多线程调用ZipFile报ValueError: I/O operation on closed file问题求解

问题根本原因
  • ZipFile对象自动回收关闭:你在extract_data函数中创建的zip_file是局部变量,当你启动子线程后函数立刻返回响应,此时zip_file没有其他有效引用,Python的垃圾回收机制会触发ZipFile的析构方法,自动调用close()关闭底层IO流,子线程后续操作已经关闭的文件对象就会抛出对应错误。
  • Flask请求资源自动清理:你上传的文件是Flask请求上下文中的FileStorage对象,当接口请求结束(post方法返回响应后),Flask会自动清理请求绑定的临时资源,FileStorage对应的文件流会被直接关闭,就算ZipFile对象没有被回收,也无法读取底层的源数据。
  • 补充代码笔误:你提供的extract_function中zipfile.open(file)是拼写错误,应该是zip_file.open(file),小写z的zipfile是模块名不是你传入的对象,这个问题也会引发执行报错。
解决方案

方案1:异步逻辑内独立创建ZipFile对象(推荐)

把压缩包的原始数据先读取出来传递给子线程,在子线程内部单独创建ZipFile对象,完全不依赖主线程的局部变量和请求上下文:

from io import BytesIO

def extract_function(zip_bytes):
    zip_file = ZipFile(BytesIO(zip_bytes))
    df_list = []
    try:
        for file in zip_file.namelist():
            if file.endswith('.csv'):
                df_list.append(pd.read_csv(zip_file.open(file)))
            else:
                # 修正原拼写错误:zip_file而非zipfile
                excel_df = pd.read_excel(zip_file.open(file), None)
                if isinstance(excel_df, dict):
                    df_list.extend(list(excel_df.values()))
                else:
                    df_list.append(excel_df)
        print(len(df_list))
    except Exception as e:
        print('Error in converting to dataframe', str(e))

def extract_data(file):
        # 先读取文件完整字节
        zip_bytes = file.read()
        # 校验逻辑也用读出来的字节做
        zip_file = ZipFile(BytesIO(zip_bytes))
        resp = validate_function(zip_file)
        if resp.status_code == 200:
            data = Thread(target=extract_function, args=[zip_bytes])
            # 设为守护线程,避免程序退出时线程挂起
            data.daemon = True
            data.start()
        return resp

方案2:本地存储临时文件(适合大压缩包)

如果压缩包体积很大,全部读入内存会占用过高资源,可以先把文件写入本地临时目录,把文件路径传给子线程,子线程读取本地文件处理,处理完成后删除临时文件即可。

不推荐方案:等待子线程执行完成再返回

如果在data.start()后加data.join()等待线程执行完再返回响应,也可以避免资源提前释放,但会导致接口响应时间大幅变长,高并发下容易触发请求超时,完全失去异步执行的意义。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 22:57:02