【问题标题】:Python base64 encoding a listPython base64编码列表
【发布时间】:2018-02-20 06:05:43
【问题描述】:

在 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'>

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

很确定这不是对 dict 或列表等对象进行编码的正确方法。如果是这样的话,有人可以告诉我如何在 Python 中编码/解码非字符串对象吗?

非常感谢。

【问题讨论】:

  • 我不是这方面的专家,但请尝试这样做:map(base64.b64encode, my_list)
  • 这将对列表的每个元素进行编码
  • 要反转,请执行map(base64.b64decode, my_list)
  • 这个练习的目的是什么? (答案可能取决于您打算如何处理编码字符串。)
  • 你不编码 Python 对象,只编码字符串。你的意思是字符串'123'还是'\1\2\3'?第一个是''.join(map(str, my_list)),第二个是''.join(map(chr, my_list))

标签: python encoding base64 decoding


【解决方案1】:

尝试使用 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 简单、易读、被广泛支持并且与其他语言交叉兼容。我会尽可能选择它。

【讨论】:

  • @DyZ 没有。 JSON 标量包括在 Python 中无效的小写布尔值和在 Python 中也找不到的“null”。最后,python 字符串表示用单引号呈现。 JSON 规范只接受双引号。我可以继续,但重点是,虽然 JSON 和 python 数据结构看起来很相似,但它们不能直接互换
  • @JoelCornett 是的,但就这个问题(数字列表)而言,差异无关紧要。
【解决方案2】:

您对正在编码的数据感兴趣,而不是正在编码的列表本身。因此我建议如下:使用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))

【讨论】:

    【解决方案3】:

    这个错误很容易解释:

    b2a_base64() 参数 1 必须是字符串或缓冲区,而不是列表

    调用一个将获取列表的编码方法怎么样?

    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 以获取原始列表。因为 eval 可以执行字符串中的任意代码,例如删除硬盘的命令,所以您不想评估不受信任的字符串。虽然,泡菜模块的文档包含类似的警告。

    【讨论】:

    • 对于基本数据结构,别忘了ast.literal_eval
    猜你喜欢
    • 2017-01-02
    • 1970-01-01
    • 2019-01-18
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    相关资源
    最近更新 更多