7

执行以下行时收到错误消息:

img = copy.deepcopy(img_file_obj)

具有以下img_file_obj类型:

<class 'werkzeug.datastructures.FileStorage'>

是否不允许创建文件存储对象的深层副本?

添加

我可能需要解释为什么我要尝试创建文件存储对象的副本。在我的代码结束时,我执行:

img_obj.save(fname)

但在此之前,我会检查文件有多大。我通过以下方式进行操作:

img_obj.seek(0, os.SEEK_END)
size = img.tell()

问题是检查大小会“破坏”文件。如果我检查文件大小然后保存它,我会在磁盘上得到一个空文件。这就是为什么我想创建文件对象的副本,检查副本的大小,如果大小可以接受,则将原始文件对象保存在磁盘上。

4

3 回答 3

5

是否存在无法为其创建深层副本的对象?

是的。

__deepcopy__任何其类型使用(或注册copyreg)引发异常的函数覆盖标准的对象都不能被深度复制。

任何类型使用标准__deepcopy__但不能(浅)复制的对象都不能深复制。

任何具有无法深度复制的子元素(无论是由标准选择__deepcopy__还是其自己的实现)的对象都不能进行深度复制。

并且有很多种对象甚至不能进行浅拷贝。该copy模块的文档提供了一些示例:

此模块不复制模块、方法、堆栈跟踪、堆栈帧、文件、套接字、窗口、数组或任何类似类型等类型。

并不是说不可能复制文件,而是它的含义很模糊(应该复制文件句柄,重新打开文件还是共享句柄?应该以相同的文件指针开头?它的缓冲区或有状态编码器必须处于相同的状态?),因此使它们可复制会更具误导性而不是帮助。

当然,Werkzeug 框架本可以选择使其FileStorage对象可复制,即使标准 Python 文件对象不可复制,但他们大概有同样的理由不这样做。

于 2014-09-06T05:08:35.313 回答
2

当然可以创建一种无法深度复制的类型。 文档说:

为了让一个类定义它自己的复制实现,它可以定义特殊的方法__copy__()__deepcopy__().

因此,一个类可以通过在此处引发异常来使其自身不可深度复制。

从概念上讲,像文件这样的东西只是不太可能被深度复制的东西类型。制作文件之类的深层副本可能涉及复制磁盘上的实际文件。如果文件很大,那可能会很昂贵;如果用户没有正确的权限,或者磁盘已满等,这可能是不可能的。尝试复制一些不限于程序本身。因此,引用外部资源的对象可能无法深度复制;如果您真的想对它们进行深度复制,则必须手动复制外部资源并创建一个新对象。

于 2014-09-06T05:07:50.263 回答
1

copy模块的文档中:

此模块不复制模块、方法、堆栈跟踪、堆栈帧、文件、套接字、窗口、数组或任何类似类型等类型。

由于werkzeug.datastructures.FileStorage“传入文件的薄包装”file ,我会说它与上面引用的文本一样算作“相似类型” 。

于 2014-09-06T05:10:22.790 回答