Python的泡菜是否在r + b模式下工作?

时间:2017-06-16 17:42:14

标签: 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)

为什么第二个代码不起作用?有没有办法更新文件内容而无需打开文件两次?

1 个答案:

答案 0 :(得分:1)

更新2:

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

如果您担心正在读取/写入'r+b'模式的数据大小,RAM中的大小更像是读/写的问题。您没有跳过该步骤的时间,cpu周期或磁盘操作。

还有可读性。考虑原始版本'rb''wb'(4行,易于理解)与“在一个块中执行”方法中的6。明确的seek(0)truncate()无论如何都会在单独的'wb'块中发生。也可能影响性能。单块方法没有任何好处,读取和写入容易出错 - 需要3次编辑才能修复单块方法创建的问题。 : - /

原始答案:

正如@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:

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