`pickle.dump(d, f)` 是否等同于 `f.write(pickle.dumps(d))`?

Is `pickle.dump(d, f)` equivalent to `f.write(pickle.dumps(d))`?

给定一个任意的 picklable Python 数据结构 data,是

with open('a', 'bw') as f:
    f.write(pickle.dumps(data))

相当于

with open('a', 'bw') as f:
    pickle.dump(data, f)

即我可以在编写代码时假定这种等价性吗?您能描述一下您是如何得出这个结论的吗?

用例是将序列化与写入分开,因为我可能想将 pickle 写入非磁盘位置。

是的。

documentation of dumps 很清楚:

Return the pickled representation of the object as a bytes object, instead of writing it to a file.

将相同的表示写入文件与直接调用 pickle.dump 相同。

此外,"file" 在这里表示任何具有 write 方法的东西,来自 documentation of dump:

The file argument must have a write() method that accepts a single bytes argument. It can thus be an on-disk file opened for binary writing, an io.BytesIO instance, or any other custom object that meets this interface.

是的,它们是等价的。查看pickle.py的源代码:

def _dump(obj, file, protocol=None, *, fix_imports=True):
    _Pickler(file, protocol, fix_imports=fix_imports).dump(obj)

def _dumps(obj, protocol=None, *, fix_imports=True):
    f = io.BytesIO()
    _Pickler(f, protocol, fix_imports=fix_imports).dump(obj)
    res = f.getvalue()
    assert isinstance(res, bytes_types)
    return res

dumps 做与 dump 完全相同的事情,只是使用 io.BytesIO 对象而不是文件对象。它以相同的方式调用内部 _Pickler().dump() 并简单地 returns io.BytesIO 对象的内容。因此,f.write(pickle.dumps(data)) 所做的只是首先将结果转发给 io.BytesIO 对象,然后转发给实际文件,而不是直接写入文件。

如果酸洗过程中出现异常,它们是不等价的。 f.write(pickle.dumps(data)) 不会向文件写入任何内容。而 pickle.dump(data, f) 将以折断或部分泡菜结束。