使用 Base64 和 Pickle 编码和解码

Encode and Decode with Base64 and Pickle

我需要 pickle 一个字典,然后在通过 API 调用传输数据之前对其进行 Base64 编码..

接收方应解码 Base64 数据,然后 pickle 将其加载回正确的字典。

问题是解码失败,解码 Base64 数据后似乎不是相同的二进制数据,因此 Pickle 失败。

我错过了什么?

import pickle
import base64
import json

def publishData():
   testDict = {}
   testDict['testKey1'] = [1,2,3]
   testDict['testKey2'] = [4,5,6]
   #Dump the dict to pickle file
   with open("test.pkl","wb") as f:
      pickle.dump(testDict, f)
   #Read the pickle
   with open("test.pkl", "rb") as openfile:
      data = openfile.read() #Read the raw pickle (binary)
   print("publishData - Pickle read : {}".format(data))
   #Base64 encode it to ensure formatting in JSON
   data = base64.b64encode(data)
   print("publishData - Base64 encoded : {}".format(data))
   #Create a json to be published via API
   publishJson = json.dumps({"payload":str(data)})
   print("publishData - Publish JSON : {}".format(publishJson))
   #Decode the data
   decodeData(publishJson)

def decodeData(publishJson):
   data = json.loads(publishJson)
   payload = data['payload']
   payload = base64.b64decode(payload)
   print("decodeData - Payload decoded: {}".format(payload))
   print(pickle.loads(payload))

if __name__ == "__main__":
   publishData()

输出:

publishData - Pickle read : b'\x80\x04\x95/\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x08testKey1\x94]\x94(K\x01K\x02K\x03e\x8c\x08testKey2\x94]\x94(K\x04K\x05K\x06eu.'
publishData - Base64 encoded : b'gASVLwAAAAAAAAB9lCiMCHRlc3RLZXkxlF2UKEsBSwJLA2WMCHRlc3RLZXkylF2UKEsESwVLBmV1Lg=='
publishData - Publish JSON : {"payload": "b'gASVLwAAAAAAAAB9lCiMCHRlc3RLZXkxlF2UKEsBSwJLA2WMCHRlc3RLZXkylF2UKEsESwVLBmV1Lg=='"}
decodeData - Payload decoded: b'n\x00\x12T\xbc\x00\x00\x00\x00\x00\x00\x01\xf6P\xa20!\xd1\x95\xcd\xd1-\x95\xe4\xc6QvP\xa1,\x05,\t,\r\x960!\xd1\x95\xcd\xd1-\x95\xe4\xcaQvP\xa1,\x11,\x15,\x19\x95\xd4\xb8'

_pickle.UnpicklingError: invalid load key, 'n'.

调用 data.decode() 或等效的 str(data, encoding='utf-8') 将字节转换为有效的 base64 编码字符串:

# publishJson = json.dumps({"payload": str(data)})     # -
publishJson = json.dumps({"payload": data.decode())})  # +

来自 https://docs.python.org/3/library/stdtypes.html#str:

Passing a bytes object to str() without the encoding or errors arguments falls under the first case of returning the informal string representation

print(data)                 #  b'gASVLwAAAAAAAAB9lCiMCHRlc3RLZXkxlF2UKEsBSwJLA2WMCHRlc3RLZXkylF2UKEsESwVLBmV1Lg=='
print(repr(data))           #  b'gASVLwAAAAAAAAB9lCiMCHRlc3RLZXkxlF2UKEsBSwJLA2WMCHRlc3RLZXkylF2UKEsESwVLBmV1Lg=='

print(str(data))            #  b'gASVLwAAAAAAAAB9lCiMCHRlc3RLZXkxlF2UKEsBSwJLA2WMCHRlc3RLZXkylF2UKEsESwVLBmV1Lg=='
print(repr(str(data)))      # "b'gASVLwAAAAAAAAB9lCiMCHRlc3RLZXkxlF2UKEsBSwJLA2WMCHRlc3RLZXkylF2UKEsESwVLBmV1Lg=='"

print(data.decode())        #    gASVLwAAAAAAAAB9lCiMCHRlc3RLZXkxlF2UKEsBSwJLA2WMCHRlc3RLZXkylF2UKEsESwVLBmV1Lg==
print(repr(data.decode()))  #   'gASVLwAAAAAAAAB9lCiMCHRlc3RLZXkxlF2UKEsBSwJLA2WMCHRlc3RLZXkylF2UKEsESwVLBmV1Lg=='