Python2/3下设置delete=False的Django TemporaryUploadedFile行为差异咨询
差异原因说明
你遇到的版本差异本质是Python2和Python3标准库tempfile.NamedTemporaryFile的实现差异,叠加Django 1.11的封装逻辑导致的:
- Python2.7环境下,
tempfile.NamedTemporaryFile的delete是公开可修改的实例属性,你执行tmp_file.file.delete = False直接修改了控制删除逻辑的标志位,文件关闭时会跳过删除步骤,自然就保留在/tmp目录下。 - Python3环境下,
tempfile.NamedTemporaryFile的delete改为了仅可读的属性,底层实际控制删除逻辑的是私有变量_delete。你执行tmp_file.file.delete = False只是给实例额外新增了一个无意义的同名属性,并没有修改到底层的删除开关,所以文件退出with块关闭时还是会被自动删除。
Python3环境下保留临时文件的实现方案
方案1:修改底层私有变量(适配当前版本,兼容性一般)
直接修改tempfile.NamedTemporaryFile实例的私有控制变量_delete,修改后的测试代码如下,可同时兼容Python2和Python3环境:
from django.core.files.uploadedfile import TemporaryUploadedFile with TemporaryUploadedFile('something.txt', 'text/plain', 0, 'UTF-8') as tmp_file: tmp_file_path = tmp_file.temporary_file_path() # 适配Python3的修改逻辑 if hasattr(tmp_file.file, '_delete'): tmp_file.file._delete = False # 兼容Python2的逻辑 else: tmp_file.file.delete = False print(tmp_file_path)
注意:该方案依赖当前Python和Django的内部实现,升级版本后可能失效。
方案2:手动持久化临时文件(无版本依赖,更稳妥)
不需要修改临时文件的内部属性,直接在with块内将临时文件拷贝到你指定的持久化目录,不管后续临时文件是否被删除,都能拿到完整的文件内容:
import shutil from django.core.files.uploadedfile import TemporaryUploadedFile # 替换为你自己的持久化存储路径 target_path = "/opt/data/something.txt" with TemporaryUploadedFile('something.txt', 'text/plain', 0, 'UTF-8') as tmp_file: tmp_file.seek(0) with open(target_path, 'wb') as f: shutil.copyfileobj(tmp_file, f) print(f"文件已持久化到: {target_path}")
内容的提问来源于stack exchange,提问作者Ray Tango
相关产品推荐
相关产品推荐

