Python 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

我正在尝试将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(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。重点是对象应该“压缩”,而不是保存在任何文件中。只需存储在变量中并通过请求发送即可。