在 Python 2.7 中 save/load 一个大列表的最快方法是什么?
What's the fastest way to save/load a large list in Python 2.7?
在 Python 2.7 中 save/load 一个大列表的最快方法是什么?如果有人问过这个问题,我深表歉意,我在搜索时找不到这个确切问题的答案...
更具体地说,我正在测试模拟某些东西的方法,我需要将我测试的每种方法的结果与精确解进行比较。我有一个 Python 脚本,它生成代表精确解的值列表,我不想每次 运行 新模拟时都重新计算它。因此,我想将它保存在某处并加载解决方案,而不是每次我想查看我的模拟结果有多好时都重新计算它。
我也不需要保存的文件是人类可读的。我只需要能够在 Python.
中加载它
您可能想看看 Python 对象序列化,pickle
和 cPickle
http://pymotw.com/2/pickle/
pickle.dumps(obj[, protocol])
如果省略协议参数,则使用协议 0。如果协议指定为负值或 HIGHEST_PROTOCOL,将使用最高协议版本。
正如 PadraicCunningham 所提到的,您可以对列表进行 pickle。
import pickle
lst = [1,2,3,4,5]
with open('file.pkl', 'wb') as pickle_file:
pickle.dump(lst, pickle_file, protocol=pickle.HIGHEST_PROTOCOL)
这会将列表加载到文件中。
并提取它:
import pickle
with open('file.pkl', 'rb') as pickle_load:
lst = pickle.load(pickle_load)
print(lst) # prints [1,2,3,4,5]
HIGHEST_PROTOCOL
位是可选的,但通常建议使用。协议定义了 pickle 将如何序列化对象,较低的协议倾向于与旧版本的 Python.
兼容
还有两点值得注意:
还有 cPickle
模块 - 用 C 语言编写以优化速度。你的使用方法和上面一样。
Pickle 也有一些不安全因素(有一些方法可以操纵 pickle 如何反序列化对象,您可以操纵它使 Python 做更多或更少的事情)。因此,当打开未知数据时不应使用该库。在极端情况下,您可以尝试更安全的版本,例如 spickle
:https://github.com/ershov/sPickle
我推荐查找的其他库是 json
和 marshall
。
使用 np.load 和 tolist 比任何其他解决方案都快得多:
In [77]: outfile = open("test.pkl","w")
In [78]: l = list(range(1000000))
In [79]: timeit np.save("test",l)
10 loops, best of 3: 122 ms per loop
In [80]: timeit np.load("test.npy").tolist()
10 loops, best of 3: 20.9 ms per loop
In [81]: timeit pickle.load(outfile)
1 loops, best of 3: 1.86 s per loop
In [82]: outfile = open("test.pkl","r")
In [83]: timeit pickle.load(outfile)
1 loops, best of 3: 1.88 s per loop
In [84]: cPickle.dump(l,outfile)
....:
1 loops, best of 3:
273 ms per loop
In [85]: outfile = open("test.pkl","r")
In [72]: %%timeit
cPickle.load(outfile)
....:
1 loops, best of 3:
539 ms per loop
在 python 3 中,如果使用 numpy 数组,numpy 的效率要高得多:
In [24]: %%timeit
out = open("test.pkl","wb")
pickle.dump(l, out)
....:
10 loops, best of 3: 27.3 ms per loop
In [25]: %%timeit
out = open("test.pkl","rb")
pickle.load(out)
....:
10 loops, best of 3: 52.2 ms per loop
In [26]: timeit np.save("test",l)
10 loops, best of 3: 115 ms per loop
In [27]: timeit np.load("test.npy")
100 loops, best of 3: 2.35 ms per loop
如果你想要一个列表,再次调用 tolist 并使用 np.load:
会更快
In [29]: timeit np.load("test.npy").tolist()
10 loops, best of 3: 37 ms per loop
我已经对许多方法(numpy 方法除外)进行了一些分析,pickle/cPickle 在简单数据集上非常慢。最快的方法取决于您保存的数据类型。如果要保存字符串列表 and/or 个整数。我见过的最快的方法是使用 for 循环和 ','.join(...)
将它直接写入文件;使用与 .split(',')
.
类似的 for 循环读回
在 Python 2.7 中 save/load 一个大列表的最快方法是什么?如果有人问过这个问题,我深表歉意,我在搜索时找不到这个确切问题的答案...
更具体地说,我正在测试模拟某些东西的方法,我需要将我测试的每种方法的结果与精确解进行比较。我有一个 Python 脚本,它生成代表精确解的值列表,我不想每次 运行 新模拟时都重新计算它。因此,我想将它保存在某处并加载解决方案,而不是每次我想查看我的模拟结果有多好时都重新计算它。
我也不需要保存的文件是人类可读的。我只需要能够在 Python.
中加载它您可能想看看 Python 对象序列化,pickle
和 cPickle
http://pymotw.com/2/pickle/
pickle.dumps(obj[, protocol])
如果省略协议参数,则使用协议 0。如果协议指定为负值或 HIGHEST_PROTOCOL,将使用最高协议版本。
正如 PadraicCunningham 所提到的,您可以对列表进行 pickle。
import pickle
lst = [1,2,3,4,5]
with open('file.pkl', 'wb') as pickle_file:
pickle.dump(lst, pickle_file, protocol=pickle.HIGHEST_PROTOCOL)
这会将列表加载到文件中。
并提取它:
import pickle
with open('file.pkl', 'rb') as pickle_load:
lst = pickle.load(pickle_load)
print(lst) # prints [1,2,3,4,5]
HIGHEST_PROTOCOL
位是可选的,但通常建议使用。协议定义了 pickle 将如何序列化对象,较低的协议倾向于与旧版本的 Python.
还有两点值得注意:
还有 cPickle
模块 - 用 C 语言编写以优化速度。你的使用方法和上面一样。
Pickle 也有一些不安全因素(有一些方法可以操纵 pickle 如何反序列化对象,您可以操纵它使 Python 做更多或更少的事情)。因此,当打开未知数据时不应使用该库。在极端情况下,您可以尝试更安全的版本,例如 spickle
:https://github.com/ershov/sPickle
我推荐查找的其他库是 json
和 marshall
。
使用 np.load 和 tolist 比任何其他解决方案都快得多:
In [77]: outfile = open("test.pkl","w")
In [78]: l = list(range(1000000))
In [79]: timeit np.save("test",l)
10 loops, best of 3: 122 ms per loop
In [80]: timeit np.load("test.npy").tolist()
10 loops, best of 3: 20.9 ms per loop
In [81]: timeit pickle.load(outfile)
1 loops, best of 3: 1.86 s per loop
In [82]: outfile = open("test.pkl","r")
In [83]: timeit pickle.load(outfile)
1 loops, best of 3: 1.88 s per loop
In [84]: cPickle.dump(l,outfile)
....:
1 loops, best of 3:
273 ms per loop
In [85]: outfile = open("test.pkl","r")
In [72]: %%timeit
cPickle.load(outfile)
....:
1 loops, best of 3:
539 ms per loop
在 python 3 中,如果使用 numpy 数组,numpy 的效率要高得多:
In [24]: %%timeit
out = open("test.pkl","wb")
pickle.dump(l, out)
....:
10 loops, best of 3: 27.3 ms per loop
In [25]: %%timeit
out = open("test.pkl","rb")
pickle.load(out)
....:
10 loops, best of 3: 52.2 ms per loop
In [26]: timeit np.save("test",l)
10 loops, best of 3: 115 ms per loop
In [27]: timeit np.load("test.npy")
100 loops, best of 3: 2.35 ms per loop
如果你想要一个列表,再次调用 tolist 并使用 np.load:
会更快In [29]: timeit np.load("test.npy").tolist()
10 loops, best of 3: 37 ms per loop
我已经对许多方法(numpy 方法除外)进行了一些分析,pickle/cPickle 在简单数据集上非常慢。最快的方法取决于您保存的数据类型。如果要保存字符串列表 and/or 个整数。我见过的最快的方法是使用 for 循环和 ','.join(...)
将它直接写入文件;使用与 .split(',')
.