python - 在 Python 3.6 中保存/加载大量字符串(列表/集)的最快方法是什么?
问题描述
该文件长 5GB。
我确实在 stackoverflow 上发现了一个类似的问题,人们建议使用 numpy 数组,但我认为这个解决方案适用于数字集合而不是字符串。
会有什么比 eval(list.txt) 或导入一个变量设置为列表的 python 文件吗?
加载/保存python字符串列表的最有效方法是什么?
解决方案
对于只读情况:
import numpy as np
class IndexedBlob:
def __init__(self, filename):
index_filename = filename + '.index'
blob = np.memmap(filename, mode='r')
try:
# if there is an existing index
indices = np.memmap(index_filename, dtype='>i8', mode='r')
except FileNotFoundError:
# else, create it
indices, = np.where(blob == ord('\n'))
# force dtype to predictable file
indices = np.array(indices, dtype='>i8')
with open(index_filename, 'wb') as f:
# add a virtual newline
np.array(-1, dtype='>i8').tofile(f)
indices.tofile(f)
# then reopen it as a file to reduce memory
# (and also pick up that -1 we added)
indices = np.memmap(index_filename, dtype='>i8', mode='r')
self.blob = blob
self.indices = indices
def __getitem__(self, line):
assert line >= 0
lo = self.indices[line] + 1
hi = self.indices[line + 1]
return self.blob[lo:hi].tobytes().decode()
一些附加说明:
- 在末尾添加新字符串(只需以附加模式打开文件并写入一行 - 但要注意以前的损坏写入)很容易 - 但也要记住手动更新索引文件。
mmap
但请注意,如果您想查看现有IndexedBlob
对象,则需要重新设置。您可以避免这种情况,只需保留“松散”对象的列表。 - 按照设计,如果最后一行缺少换行符,则将其忽略(以检测截断或并发写入)
n
您可以通过仅记录每个换行符,然后在查找时进行线性搜索来显着缩小索引的大小。然而,我发现这不值得。- 如果您对开始和结束使用单独的索引,则不再受限于按顺序存储字符串,这为突变开辟了多种可能性。但如果突变很少见,重写整个文件并重新生成索引并不太昂贵。
- 考虑使用
'\0'
作为分隔符而不是'\n
.
而且当然:
- 无论您做什么,一般并发突变都很难。如果您需要做任何复杂的事情,请使用真正的数据库:这是当时最简单的解决方案。
推荐阅读
- operating-system - 软件类型
- import - 如果文件夹被压缩,如何将数据导入 kaggle 内核?
- javascript - 尝试通过通过 php 文件处理但不起作用的 HTML 表单上传文件?
- c# - 如何通过 UI 按钮选择游戏对象?
- python - 为什么 Python 的 max() 函数不准确?
- javascript - 如何创建用户输入(使用 javascript)
- java - 错误 java.lang.IllegalArgumentException:参数类型的名称 [java.lang.String]
- laravel - Laravel Scout 导入现有数据不起作用
- python - 使用 Tkinter 将内容对齐到中心
- python - 当字节不在对象表示法中时,将 python 字节转换为 dict 或 json