我有大量的numpy ndarray被存储到字符串中。这可能是一个糟糕的设计选择,但它就是我做的,现在挑选的字符串似乎已被转换或沿途的东西,当我尝试unpickle我注意到它们是str
类型,我得到了以下错误:
TypeError: 'str' does not support the buffer interface
当我调用
时numpy.loads(bin_str)
bin_str
是我试图解开的东西。如果我打印出bin_str
,它看起来像是
b'\x80\x02cnumpy.core.multiarray\n_reconstruct\nq\x00cnumpy\nndarray\nq\x01K\x00\x85q\x02c_codecs\nencode\nq\x03X\x01\x00\x00\ ...
持续一段时间,所以信息似乎在那里,我只是不太确定如何将其转换为numpy / pickle需要的任何字符串格式。我一时兴起尝试
numpy.loads( bytearray(bin_str, encoding='utf-8') )
和
numpy.loads( bin_str.encode() )
两者都抛出错误_pickle.UnpicklingError: unpickling stack underflow
。有什么想法吗?
PS:我在python 3.3.2和numpy 1.7.1
修改
我发现如果我执行以下操作:
open('temp.txt', 'wb').write(...)
return numpy.load( 'temp.txt' )
我收回了我的数组,...
表示从另一个窗口复制并粘贴 print(bin_str)
的输出。我已经尝试将bin_str
直接写入文件,但这不起作用,它会抱怨TypeError: 'str' does not support the buffer interface
。将bin_str
转换为可以直接写入二进制文件的一些合理方法会在尝试将其读回时导致pickle错误。
编辑2 所以我想发生的事情是我的二进制泡菜字符串最终在普通字符串中编码,如:
"b'pickle'"
这是不幸的,我还没弄清楚如何处理这个问题,除了这种荒谬和错综复杂的方式来取回它:
open('temp.py', 'w').write('foo = ' + bin_str)
from temp import foo
numpy.loads( foo )
这似乎是解决问题的一个非常可耻的解决方案,所以请给我一个更好的解决方案!
答案 0 :(得分:2)
听起来您保存的字符串是您的酸洗代码返回的原始repr
实例的bytes
。这有点不幸,但也不算太糟糕。 repr
旨在返回对象的“机器友好”表示,通常可以使用eval
来反转:
import numpy as np
import pickle
# this part has already happened
orig_obj = np.array([1,2,3])
orig_pickle = pickle.dumps(orig_obj)
saved_str = repr(orig_pickle) # this was a mistake, but it's already done
# this is what you need to do to get something equivalent to orig_obj back
reconstructed_pickle = eval(saved_str)
reconstructed_obj = pickle.loads(reconstructed_pickle)
# test
if np.all(reconstructed_obj == orig_obj):
print("It worked!")
使用eval
的强制性说明可能很危险:请注意eval
可以运行它想要的任何Python代码,因此不要使用不受信任的数据调用它。但是,pickle数据具有相同的风险(恶意的Pickle字符串可以在unpickling时运行任意代码),因此在这种情况下你不会失去很多安全性。无论如何,我猜你在这种情况下信任你的数据。