Python base64编码然后解码通用对象

lor*_*zin 5 python base64 encoding serialization numpy

我正在尝试将 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))
Run Code Online (Sandbox Code Playgroud)

有没有办法取回原始变量?

一般问题是:我可以将“任何”对象转换为二进制字符串,然后转换回原始类型吗?

我也许可以使用 pickle 但我需要压缩格式(不在文件中):类似

x_compressed = zipped(pickle.dumps(x))
Run Code Online (Sandbox Code Playgroud)

Jam*_*mes 5

我不确定您想要完成什么,但您可以对任何具有bytes表示形式的对象进行 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'
Run Code Online (Sandbox Code Playgroud)

由于我们有bytes数组的表示形式,因此您可以将其传递给 Base64 编码器。请注意,如果对象不是类字节对象,它将base64在编码之前尝试对其进行转换,如下例所示:

base64.b64encode(x)
# returns
b'AQAAAAIAAAADAAAA'

base64.b64encode(x.tobytes())
# returns
b'AQAAAAIAAAADAAAA'
Run Code Online (Sandbox Code Playgroud)

字节数组没什么特别的。它只是一个数字序列!就是这样。您之所以没有恢复 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])
Run Code Online (Sandbox Code Playgroud)

如果您想保存一个对象并稍后恢复它,该过程称为序列化。有两个非常好的处理序列化的包,第一个是标准库中的 call pickle,第二个是 call 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])
Run Code Online (Sandbox Code Playgroud)