python - Python 的 pickle 是否以 r+b 模式工作?

标签 python pickle

假设我使用 pickle.dump 来存储一个整数值,并且我想通过加 1 来更新该整数。以下代码有效:

with open('../CONFIG.txt', 'rb') as ofile:
    value = pickle.load(ofile)

with open('../CONFIG.txt', 'wb') as ofile:
    pickle.dump(value + 1, ofile, protocol=2)

但是一旦我使用 r+b 模式,它就不会:

with open('../CONFIG.txt', 'r+b') as ofile:
    value = pickle.load(ofile)
    pickle.dump(value + 1, ofile, protocol=2)

为什么第二个代码不起作用?有没有办法在不打开文件两次的情况下更新文件内容?

最佳答案

更新 2:

如果您确实需要使用同一个文件读取和写入 pickle 数据,最好单独执行,一次使用 'r',然后使用 'w'模式。 “打开文件”的行为并不像读取或写入文件那么昂贵。打开文件,也称为获取文件句柄,速度相当快。

如果您关心 'r+b' 模式下读取/写入的数据大小,则 RAM 中的大小比读取/写入更重要。您不会跳过时间、CPU 周期或磁盘操作的该步骤。

还有可读性。考虑使用 'rb''wb' 的原始版本(4 行,易于理解)与“在一个 block 中完成”方法中的 6 行。显式的 seek(0)truncate() 无论如何都会在单独的 'wb' block 中发生。可能也会影响性能。单 block 方法没有任何好处,读取起来更差,写入时容易出错 - 需要 3 次编辑才能解决单 block 方法产生的问题。 :-/

原始答案:

正如 @glibdud 在评论中提到的,执行 pickle.load() 后,文件指针将移至末尾。

如果您想使用'r+b'模式将数据写回文件,则使用ofile.seek()修改光标的位置。在这种情况下,输入 ofile.seek(0)将光标移回文件开头。

>>> with open('CONFIG.txt', 'r+b') as ofile:
...     value = pickle.load(ofile)
...     print value
...     # re-position the cursor to the start of the file before dumping new data
...     ofile.seek(0)
...     pickle.dump(value + 1, ofile, protocol=2)
...     # truncate anything left in the file if the prev pickled data was larger
...     ofile.truncate()
...
3
>>> 
>>> # let's read again to see
...
>>> with open('CONFIG.txt', 'r+b') as ofile:
...     value = pickle.load(ofile)
...     print value
...
4
>>>

更新 1 和 3:

Wrt @user2357112 关于截断文件的评论:我认为没有必要。我用pickle转储了一个较长的文本,然后让它只写一个int,它似乎已经正确覆盖了。也许转储文件需要更大才能验证是否存在问题;或者协议(protocol) 0 的 ascii 格式容易受到它的影响,而协议(protocol) >= 1 的二进制格式则更容易受到影响。 更正: 如注释中所述,额外的数据仍在文件中。所以file.truncate()是需要的。请参阅下面的评论。幸运的是,在默认用法(无参数)中,它会截断到当前位置。

关于python - Python 的 pickle 是否以 r+b 模式工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44595113/

相关文章:

python - 制作 pacman 游戏,但不知道如何在碰撞后移除 pac 颗粒

python - 使用日志记录的 TimedRotatingFileHandler 创建 .log 文件

python - 转换并加入多个嵌套的列表列表

python - 使用类(高效创建类,每帧绘制和更新类的所有实例)

python - 如何在 numpy.append 中短路扁平化

python - 在 Python 中使用模块 PICKLE 打开 Matlab 文件 .mat

python - UnpicklingError 加载 key 无效, '{'

python - write() 参数必须是 str,而不是 bytes

python - 在 pickle 中存储数据时出现 IO 错误

python - 从 pickle 文件加载并修改 tkinter gui