【问题标题】:What is the best way to save a complex dictionary to file?将复杂字典保存到文件的最佳方法是什么?
【发布时间】:2018-10-02 11:35:04
【问题描述】:

我有一个包含元组键和 numpy 数组值的字典。我尝试使用 h5 和 pickle 保存它,但我收到错误消息。将此对象保存到文件的最佳方法是什么?

import numpy as np
from collections import defaultdict
Q =defaultdict(lambda: np.zeros(2))
Q[(1,2,False)] = np.array([1,2])
Q[(1,3,True)] = np.array([3,4])

>>> Q
defaultdict(<function <lambda> at 0x10c51ce18>, {(1, 2, False): array([1, 2]), (1, 3, True): array([3, 4])})

np.save 回溯:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-99-a071e1561501> in <module>()
----> 1 np.save('Q.npy', Q)

~/anaconda3_420/lib/python3.5/site-packages/numpy/lib/npyio.py in save(file, arr, allow_pickle, fix_imports)
    509         arr = np.asanyarray(arr)
    510         format.write_array(fid, arr, allow_pickle=allow_pickle,
--> 511                            pickle_kwargs=pickle_kwargs)
    512     finally:
    513         if own_fid:

~/anaconda3_420/lib/python3.5/site-packages/numpy/lib/format.py in write_array(fp, array, version, allow_pickle, pickle_kwargs)
    584         if pickle_kwargs is None:
    585             pickle_kwargs = {}
--> 586         pickle.dump(array, fp, protocol=2, **pickle_kwargs)
    587     elif array.flags.f_contiguous and not array.flags.c_contiguous:
    588         if isfileobj(fp):

AttributeError: Can't pickle local object 'mc_control_epsilon_greedy.<locals>.<lambda>'

【问题讨论】:

  • 有什么错误?

标签: python numpy


【解决方案1】:

我没有发现使用 pickle 有任何问题

import pickle
import numpy as np

x = {(1,2,False): np.array([1,4]), (1,3,False): np.array([4,5])}

with open('filename.pickle', 'wb') as handle:
    pickle.dump(x, handle, protocol=pickle.HIGHEST_PROTOCOL)
with open('filename.pickle', 'rb') as handle:
    y = pickle.load(handle)

print x
print y

修改后:

您实际拥有的是lambda,默认情况下不能腌制。您需要安装dill 并导入它才能工作(请参阅this answer

它应该是这样的:

import pickle
import numpy as np
from collections import defaultdict
import dill # doesn't come with default anaconda. Install with "conda install dill"

x = defaultdict(lambda: np.zeros(2))
with open('filename.pickle', 'wb') as handle:
    pickle.dump(x, handle, protocol=pickle.HIGHEST_PROTOCOL)
with open('filename.pickle', 'rb') as handle:
    y = pickle.load(handle)

print x
print y

输出:

# no errors :-)
defaultdict(<function <lambda> at 0x000000000CD0C898>, {})
defaultdict(<function <lambda> at 0x0000000002614C88>, {})

OP 的解决方案: 您编辑的解决方案仍然对我产生了同样的错误,但这工作正常:

import pickle
import dill
dill_file = open("Q.pickle", "wb")
dill_file.write(dill.dumps(Q))
dill_file.close()

在我的机器上(Win 8.1 64 位,使用 Spyder),使用简单的dill 时没有错误。

【讨论】:

  • --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) &lt;ipython-input-100-2776507a179b&gt; in &lt;module&gt;() 1 import pickle 2 with open('fQ.pickle', 'wb') as handle: ----&gt; 3 pickle.dump(Q, handle, protocol=pickle.HIGHEST_PROTOCOL) AttributeError: Can't pickle local object 'mc_control_epsilon_greedy.&lt;locals&gt;.&lt;lambda&gt;'
  • 是否有可能您实际上是在尝试腌制另一个对象而不是字典? (通过您的错误按摩,似乎是这样)。请在问题正文中发布您的 MCVE
  • 如果它是一个 defaultdict 对象有关系吗? defaultdict(lambda: np.zeros(2))
  • 这显然很重要。你的代码不运行,我的运行。请张贴整个事情
  • 对不起,我以为我在简化帖子。显然,这不是一个好主意。我现在发布了给出错误的实际对象。
【解决方案2】:

将它保存为普通字典怎么样?保存期间不需要defaultdict 行为。

In [126]: from collections import defaultdict
In [127]: Q =defaultdict(lambda: np.zeros(2))
     ...: Q[(1,2,False)] = np.array([1,2])
     ...: Q[(1,3,True)] = np.array([3,4])
     ...: Q[(3,4,False)]
     ...: 
Out[127]: array([0., 0.])
In [128]: Q
Out[128]: 
defaultdict(<function __main__.<lambda>>,
            {(1, 2, False): array([1, 2]),
             (1, 3, True): array([3, 4]),
             (3, 4, False): array([0., 0.])})

我们可以将它从 defaultdict 包装中拉出来:

In [130]: dict(Q)
Out[130]: 
{(1, 2, False): array([1, 2]),
 (1, 3, True): array([3, 4]),
 (3, 4, False): array([0., 0.])}

然后我们可以腌制它(我使用np.save作为腌制快捷方式)

In [131]: np.save('stack49963862', np.array(dict(Q)))

load 给出一个包含这个字典的对象数组:

In [132]: P = np.load('stack49963862.npy')
In [133]: P
Out[133]: 
array({(1, 2, False): array([1, 2]), (1, 3, True): array([3, 4]), (3, 4, False): array([0., 0.])},
      dtype=object)

In [138]: P.item()
Out[138]: 
{(1, 2, False): array([1, 2]),
 (1, 3, True): array([3, 4]),
 (3, 4, False): array([0., 0.])}

我们可以通过更新轻松地重新创建 defaultdict:

In [134]: Q1 =defaultdict(lambda: np.zeros(2))
In [139]: Q1.update(P.item())
In [140]: Q1
Out[140]: 
defaultdict(<function __main__.<lambda>>,
            {(1, 2, False): array([1, 2]),
             (1, 3, True): array([3, 4]),
             (3, 4, False): array([0., 0.])})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 2015-07-13
    • 2010-09-27
    • 2011-04-26
    • 1970-01-01
    相关资源
    最近更新 更多