Python base64编码列表

Python base64 encoding a list

编码对我来说是 Python 中的新内容,我正在努力理解它。很抱歉,如果已经有人询问并回答了这个问题。

我正在尝试对 Python 列表进行编码和解码。 当我尝试直接对列表进行编码时,遇到如下错误。

>>> my_list = [1, 2, 3]
>>> encoded_list = base64.b64encode(my_list)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/base64.py", line 54, in b64encode
    encoded = binascii.b2a_base64(s)[:-1]
TypeError: b2a_base64() argument 1 must be string or buffer, not list

为了解决这个问题,我将列表对象转换为字符串并将其传递给编码函数,我能够成功地对其进行编码。

>>> encoded_list = base64.b64encode(str(my_list))
>>> encoded_list
'WzEsIDIsIDNd'

当我尝试对其进行解码时,我得到了如下所示的解码字符串。

>>> decoded_list = base64.b64decode(encoded_list)
>>> decoded_list
'[1, 2, 3]'
>>> type(decoded_list)
<type 'str'>

但是我的初衷是对一个列表进行编码和解码,而不是将列表转换为字符串,然后将字符串转换为列表。

很确定这不是对字典或列表等对象进行编码的正确方法。如果是这样,有人能告诉我如何 encode/decode 非字符串对象 Python?

非常感谢。

尝试 encoding/decoding 使用 JSON 而不是字符串。

import json
import base64

my_list = [1, 2, 3]
json_encoded_list = json.dumps(my_list)
#: '[1, 2, 3]'
b64_encoded_list = base64.b64encode(json_encoded_list)
#: 'WzEsIDIsIDNd'
decoded_list = base64.b64decode(b64_encoded_list)
#: '[1, 2, 3]'
my_list_again = json.loads(decoded_list)
#: [1, 2, 3]

但实际上,出于几乎所有存储原因,我认为没有真正的理由对您的 json 输出进行 base64 编码。只需编码和解码为 json.

my_list = [1, 2, 3]
json_encoded_list = json.dumps(my_list)
#: '[1, 2, 3]'
my_list_again = json.loads(json_encoded_list)
#: [1, 2, 3]

如果您需要比数组和字典更复杂的东西,那么可能会使用 7stud 的 pickle 方法。然而 JSON 简单、可读、广泛支持并且 cross-compatible 与其他语言。我会尽可能选择它。

这个错误很容易解释:

b2a_base64() argument 1 must be string or buffer, not list

调用一个需要列表的编码方法如何?

import pickle 

data = [ 
    1,
    "hello",
    {
        'a': [1, 2.0, 3, 4+6j],
        'b': ("character string", b"byte string"),
        'c': set([None, True, False])
    }
]

#Write encoded string to a file:
with open('data.pickle', 'wb') as f:
    pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)

#Read encoded string from file:
with open('data.pickle', 'rb') as f:
     print(f.read())  #Display the encoded string.
     f.seek(0)
     data = pickle.load(f)
     print(data)  
     print(data[2]['a'])  #Show that data is actually a python list.

--output:--
b'\x80\x04\x95\x87\x00\x00\x00\x00\x00\x00\x00]\x94(K\x01\x8c\x05hello\x94}\x94(\x8c\x01a\x94]\x94(K\x01G@\x00\x00\x00\x00\x00\x00\x00K\x03\x8c\x08builtins\x94\x8c\x07complex\x94\x93\x94G@\x10\x00\x00\x00\x00\x00\x00G@\x18\x00\x00\x00\x00\x00\x00\x86\x94R\x94e\x8c\x01c\x94\x8f\x94(\x89\x88N\x90\x8c\x01b\x94\x8c\x10character string\x94C\x0bbyte string\x94\x86\x94ue.'

[1, 'hello', {'a': [1, 2.0, 3, (4+6j)], 'c': {False, True, None}, 'b': ('character string', b'byte string')}]

[1, 2.0, 3, (4+6j)]

而且,如果您想将 base64 编码混合使用:

import pickle 
import base64

data = [ 
    1,
    "hello",
    {
        'a': [1, 2.0, 3, 4+6j],
        'b': ("character string", b"byte string"),
        'c': set([None, True, False])
    }
]

pstr = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
bstr = base64.b64encode(pstr)
print(pstr)
print(bstr)

--output:--
b'\x80\x04\x95\x87\x00\x00\x00\x00\x00\x00\x00]\x94(K\x01\x8c\x05hello\x94}\x94(\x8c\x01b\x94\x8c\x10character string\x94C\x0bbyte string\x94\x86\x94\x8c\x01c\x94\x8f\x94(\x89\x88N\x90\x8c\x01a\x94]\x94(K\x01G@\x00\x00\x00\x00\x00\x00\x00K\x03\x8c\x08builtins\x94\x8c\x07complex\x94\x93\x94G@\x10\x00\x00\x00\x00\x00\x00G@\x18\x00\x00\x00\x00\x00\x00\x86\x94R\x94eue.'

b'gASVhwAAAAAAAABdlChLAYwFaGVsbG+UfZQojAFilIwQY2hhcmFjdGVyIHN0cmluZ5RDC2J5dGUgc3RyaW5nlIaUjAFjlI+UKImITpCMAWGUXZQoSwFHQAAAAAAAAABLA4wIYnVpbHRpbnOUjAdjb21wbGV4lJOUR0AQAAAAAAAAR0AYAAAAAAAAhpRSlGV1ZS4='

pstr = base64.b64decode(bstr)
print(pstr)
new_data = pickle.loads(pstr)
print(new_data[2]['a'][0])

--output:--
----------------(compare to previous pstr)
b'\x80\x04\x95\x87\x00\x00\x00\x00\x00\x00\x00]\x94(K\x01\x8c\x05hello\x94}\x94(\x8c\x01b\x94\x8c\x10character string\x94C\x0bbyte string\x94\x86\x94\x8c\x01a\x94]\x94(K\x01G@\x00\x00\x00\x00\x00\x00\x00K\x03\x8c\x08builtins\x94\x8c\x07complex\x94\x93\x94G@\x10\x00\x00\x00\x00\x00\x00G@\x18\x00\x00\x00\x00\x00\x00\x86\x94R\x94e\x8c\x01c\x94\x8f\x94(\x89\x88N\x90ue.'

1

或者,您可以使用 eval(),gulp,评估一个字符串:

mystr = '''
[ 
    1,
    "hello",
    {
        'a': [1, 2.0, 3, 4+6j],
        'b': ("character string", b"byte string"),
        'c': set([None, True, False])
    }
]
'''

mylist = eval(mystr)
print(mylist[0])

--output:--
1

因此,您可以对列表进行字符串化,对字符串进行 base64 编码,然后对字符串进行 base64 取消编码,然后对字符串求值以取回原始列表。因为 eval 可以执行字符串中的任意代码,例如删除硬盘的命令,所以您不想评估不受信任的字符串。虽然,pickle 模块的文档包含类似的警告。

您感兴趣的是被编码的数据,而不是被编码的列表本身。因此我建议如下:使用 struct 来打包数据。

x = range(10)
import struct
y = struct.pack('<{}i'.format(len(x)), *x)
import base64
z = base64.b64encode(y)

z 现在将是列表中数据的编码。

您可以将其解码并检索列表,如下所示:

y = base64.b64decode(z)
list(struct.unpack('<{}i'.format(len(y)/4), y))