Python base64编码然后解码泛型对象
我正在尝试将numpy.ndarray转换为base64,然后再将其转换回。 base64图书馆是一条出路吗? 下面非常简单的代码甚至不能按预期工作。 我错过了什么Python base64编码然后解码泛型对象,python,numpy,serialization,encoding,base64,Python,Numpy,Serialization,Encoding,Base64,我正在尝试将numpy.ndarray转换为base64,然后再将其转换回。 base64图书馆是一条出路吗? 下面非常简单的代码甚至不能按预期工作。 我错过了什么 import numpy as np x = np.array([[1, 2, 3], [4, 5, 6]], np.int32) print(x) print(type(x)) encoded = base64.b64encode(x) decoded = base64.b64decode(encoded) print(dec
import numpy as np
x = np.array([[1, 2, 3], [4, 5, 6]], np.int32)
print(x)
print(type(x))
encoded = base64.b64encode(x)
decoded = base64.b64decode(encoded)
print(decoded)
print(type(decoded))
有没有办法恢复原始变量
一般问题是:
我可以将“any”对象转换为二进制字符串,然后再转换回原始类型吗
我可能可以使用pickle,但我需要一种压缩格式(不是在文件中):
差不多
x_compressed = zipped(pickle.dumps(x))
base64编码在这里可能不是一个很好的选择。如果您需要在可能由于遗留原因限制为ASCII的环境中存储或传输数据,这可能是一个不错的选择 对于numpy数组,有更简单的方法
tostring
和frombuffer
,但需要注意的是,您需要知道数据类型和形状。如果您使用的是固定尺寸和类型,您可以直接使用:
>>> x
array([[1, 2, 3],
[4, 5, 6]], dtype=int32)
>>> x.tostring()
b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00'
>>> np.frombuffer(x.tostring(), dtype=x.dtype).reshape(x.shape)
array([[1, 2, 3],
[4, 5, 6]], dtype=int32)
否则,只需使用numpy的序列化程序和反序列化程序,np.save
和np.load
,它们将为您处理这些详细信息:
>>> import io
>>> f = io.BytesIO()
>>> np.save(f, x)
>>> f.getvalue()
b"\x93NUMPY\x01\x00v\x00{'descr': '<i4', 'fortran_order': False, 'shape': (2, 3), } \n\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00"
>>> f.seek(0); np.load(f)
array([[1, 2, 3],
[4, 5, 6]], dtype=int32)
导入io
>>>f=io.BytesIO()
>>>np.save(f,x)
>>>f.getvalue()
b“\x93NUMPY\x01\x00v\x00{'descr':”我不确定您试图实现什么,但是您可以对任何具有
字节
表示的对象进行base-64编码。在您给出的示例中,您将numpy数组编码为base64
这是因为numpy数组有一个bytes
表单。您可以通过在数组周围包装bytes()
或使用.tobytes()
方法来访问它
import numpy as np
x = np.array([1,2,3])
bytes(x)
# returns:
b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
x.tobytes()
# returns:
b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
因为我们有一个数组的bytes
表示,您可以将它传递给base64编码器。请注意,如果对象不是类似字节的对象,它将base64
在编码之前尝试对其进行转换,如下例所示:
base64.b64encode(x)
# returns
b'AQAAAAIAAAADAAAA'
base64.b64encode(x.tobytes())
# returns
b'AQAAAAIAAAADAAAA'
字节数组没有什么特别的。它只是一个数字序列!就是这样。您之所以没有恢复numpy数组,是因为编码-解码过程仍然只剩下x.tobytes()
而不是x
本身的结果
要返回原始对象,您需要一个接口,该接口可以读取字节序列并返回某种类型的对象。幸运的是,numpy可以通过frombuffer
函数来执行此操作。但是,您需要告诉numpy它读取的字节数组类型
换句话说,您可以有一个int32
数组和一个int16
数组,它们具有相同的字节表示形式,但要恢复正确的字节表示形式,您需要告诉numpy哪种类型是正确的。因此,您需要对对象有一些了解
x = np.array([1,2,3])
# encode as base 64
x_64 = base64.b64encode(x.tobytes())
# decode back to bytes
x_bytes = base64.b64decode(x_64)
# use numpy to recreate original array of ints
np.frombuffer(x_bytes, dtype=int)
# returns:
np.array([1, 2, 3])
如果您想保存一个对象,然后在以后恢复它,这个过程称为序列化。有两个非常好的包可以处理序列化,第一个在标准库中,调用
pickle
,第二个叫做dill
,可以处理更复杂的对象
import pickle
x = np.array([1,2,3])
pickled_x = pickle.dumps(x)
# pickled_x is a bytes-object that is a hard to read by humans.
pickle.loads(x)
# returns:
np.array([1, 2, 3])
只要您知道确切的对象类型或继承类型,您就应该能够。您应该研究对象序列化谢谢。我考虑过pickle。重点是对象应该“压缩”,而不是保存在任何文件中。只需存储在变量中并通过请求发送即可。