简答
您需要将bytes-like 对象(bytes、bytearray 等)推送到base64.b64encode() 方法。这里有两种方法:
>>> import base64
>>> data = base64.b64encode(b'data to be encoded')
>>> print(data)
b'ZGF0YSB0byBiZSBlbmNvZGVk'
或者使用变量:
>>> import base64
>>> string = 'data to be encoded'
>>> data = base64.b64encode(string.encode())
>>> print(data)
b'ZGF0YSB0byBiZSBlbmNvZGVk'
为什么?
在 Python 3 中,str 对象不是 C 样式的字符数组(因此它们是不是字节数组),而是没有任何固有编码的数据结构。您可以通过多种方式对该字符串进行编码(或解释)。最常见的(也是 Python 3 中的默认值)是 utf-8,尤其是因为它向后兼容 ASCII(尽管使用最广泛的编码也是如此)。这就是当您使用 string 并在其上调用 .encode() 方法时发生的情况:Python 正在解释 utf-8 中的字符串(默认编码)并为您提供它对应的字节数组。
Python 3 中的 Base-64 编码
最初的问题标题是关于 Base-64 编码的。继续阅读 Base-64 的内容。
base64 编码采用 6 位二进制块并使用字符 AZ、az、0-9、'+'、'/' 和 '=' 对它们进行编码(某些编码使用不同的字符代替 '+ ' 和 '/')。这是一种基于 radix-64 或 base-64 数字系统的数学结构的字符编码,但它们非常不同。数学中的 Base-64 是一个类似于二进制或十进制的数字系统,您可以对整个数字进行这种基数更改,或者(如果您要转换的基数是 2 小于 64 的幂)从右到离开了。
在base64编码中,翻译是从左到右进行的;前 64 个字符就是为什么它被称为 base64 encoding。第 65 个 '=' 符号用于填充,因为编码拉取 6 位块,但它通常意味着编码的数据是 8 位字节,所以有时最后一个块中只有 2 或 4 位。
例子:
>>> data = b'test'
>>> for byte in data:
... print(format(byte, '08b'), end=" ")
...
01110100 01100101 01110011 01110100
>>>
如果您将该二进制数据解释为单个整数,那么您可以通过以下方式将其转换为 base-10 和 base-64 (table for base-64):
base-2: 01 110100 011001 010111 001101 110100 (base-64 grouping shown)
base-10: 1952805748
base-64: B 0 Z X N 0
但是,
base64 encoding 将重新分组这些数据:
base-2: 011101 000110 010101 110011 011101 00(0000) <- pad w/zeros to make a clean 6-bit chunk
base-10: 29 6 21 51 29 0
base-64: d G V z d A
所以,从数学上讲,'B0ZXN0' 是我们二进制文件的 base-64 版本。但是,base64 encoding 必须以相反的方向进行编码(因此原始数据转换为 'dGVzdA'),并且还有一个规则告诉其他应用程序在结束。这是通过用“=”符号填充结尾来完成的。因此,该数据的base64 编码为“dGVzdA==”,两个“=”符号表示当该数据被解码以使其与原始数据匹配时,需要从末尾删除两对位。
让我们测试一下,看看我是否不诚实:
>>> encoded = base64.b64encode(data)
>>> print(encoded)
b'dGVzdA=='
为什么要使用base64 编码?
假设我必须通过电子邮件向某人发送一些数据,例如以下数据:
>>> data = b'\x04\x6d\x73\x67\x08\x08\x08\x20\x20\x20'
>>> print(data.decode())
>>> print(data)
b'\x04msg\x08\x08\x08 '
>>>
我种了两个问题:
- 如果我尝试在 Unix 中发送该电子邮件,则该电子邮件将在读取
\x04 字符后立即发送,因为这是 END-OF-TRANSMISSION (Ctrl-D) 的 ASCII,因此剩余的数据将被忽略传输。
- 此外,虽然 Python 足够聪明,可以在我直接打印数据时转义我所有的邪恶控制字符,但当该字符串被解码为 ASCII 时,您可以看到“msg”不存在。那是因为我使用了三个
BACKSPACE 字符和三个SPACE 字符来擦除“味精”。因此,即使我没有 EOF 字符,最终用户也无法将屏幕上的文本转换为真实的原始数据。
这只是一个演示,向您展示简单地发送原始数据是多么困难。将数据编码为 base64 格式可为您提供完全相同的数据,但格式可确保通过电子邮件等电子媒体安全发送。