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

Tornado流式分块上传时data_received异常如何正确关闭文件对象

问题根因

启用stream_request_body装饰器后,data_received方法由Tornado底层的连接处理逻辑直接调用,一旦抛出未捕获的异常,会直接中断整个请求流程,不会执行后续的post方法,因此post方法中定义的文件关闭逻辑无法触发,导致文件句柄泄漏。

解决方案

方案1:使用on_finish钩子作为兜底资源释放(推荐)

Tornado的RequestHandler内置的on_finish钩子会在请求生命周期的最后阶段统一执行,无论请求过程是否出现异常,都会被调用,是释放资源的最优位置。

修改后的完整代码如下:

from tornado.ioloop import IOLoop
from tornado.web import Application, RequestHandler, stream_request_body
import os # 可选,用于异常场景下清理不完整文件

@stream_request_body
class UploadHandler(RequestHandler):

    def prepare(self):
        self.file = open('uploaded_file', 'wb')
        self.upload_success = False # 可选,用于标记上传是否完成

    def data_received(self, chunk):
        print(len(chunk))
        self.file.write(chunk)
        # 强制抛出异常测试
        raise Exception('Error')

    def post(self, *args, **kwargs):
        self.upload_success = True
        self.write('UPLOADED')
    
    def on_finish(self):
        # 兜底关闭文件,所有场景都能覆盖
        if hasattr(self, 'file') and not self.file.closed:
            self.file.close()
        # 可选逻辑:上传失败时删除不完整的临时文件
        if not self.upload_success and os.path.exists('uploaded_file'):
            os.remove('uploaded_file')


app = Application([(r'/upload', UploadHandler), ],
                  debug=True)


if __name__ == '__main__':
    app.listen(7777)
    IOLoop.current().start()

该方案侵入性极低,不需要修改现有上传业务逻辑,所有资源释放逻辑统一管理,不会出现遗漏。

方案2:在data_received内捕获异常主动处理

如果需要针对上传过程的异常给客户端返回明确的错误响应,避免客户端出现连接断开的报错,可以在data_received内部新增异常捕获逻辑:

def data_received(self, chunk):
    try:
        print(len(chunk))
        self.file.write(chunk)
        # 强制抛出异常测试
        raise Exception('Error')
    except Exception as e:
        # 先关闭已打开的文件
        if hasattr(self, 'file') and not self.file.closed:
            self.file.close()
        # 返回错误响应给客户端
        self.set_status(500)
        self.write(f"上传失败:{str(e)}")
        # 中断后续请求处理流程
        self.finish()

两种方案可以搭配使用,on_finish作为兜底的资源释放逻辑,data_received内的异常捕获做业务层的错误响应处理,双重保障文件资源不会泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 17:48:03