为什么需要“b”来使用 Base64 编码字符串?

2025-02-14 09:50:00
admin
原创
43
摘要:问题描述:我遵循了文档中有关如何在 Python 中使用 Base64 编码的示例:>>> import base64 >>> encoded = base64.b64encode(b'data to be encoded') >>> encoded b'...

问题描述:

我遵循了文档中有关如何在 Python 中使用 Base64 编码的示例:

>>> import base64
>>> encoded = base64.b64encode(b'data to be encoded')
>>> encoded
b'ZGF0YSB0byBiZSBlbmNvZGVk'

但是,如果我尝试对普通字符串进行编码-省略前导b

>>> encoded = base64.b64encode('data to be encoded')

我得到了一个TypeError。在旧版本的 Python 中它看起来像:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:Python32libase64.py", line 56, in b64encode
    raise TypeError("expected bytes, not %s" % s.__class__.__name__)
TypeError: expected bytes, not str

在较新的版本中它可能看起来像:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.12/base64.py", line 58, in b64encode
    encoded = binascii.b2a_base64(s, newline=False)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: a bytes-like object is required, not 'str'

为什么会发生这种情况?


解决方案 1:

base64 编码采用 8 位二进制字节数据,并仅使用字符A-Za-z0-9+/* 对其进行编码,因此它可以通过不保留所有 8 位数据的通道(例如电子邮件)进行传输。

因此,它需要一个 8 位字节字符串。您可以使用 Python 3 中的b''语法创建它们。

如果删除b,它就变成了一个字符串。字符串是 Unicode 字符的序列。base64 不知道如何处理 Unicode 数据,它不是 8 位的。事实上,它实际上不是任何位。:-)

在你的第二个例子中:

>>> encoded = base64.b64encode('data to be encoded')

所有字符都恰好适合 ASCII 字符集,因此 base64 编码实际上毫无意义。你可以将其转换为 ascii,方法是

>>> encoded = 'data to be encoded'.encode('ascii')

或者更简单:

>>> encoded = b'data to be encoded'

在这种情况下,情况是一样的。


  • 大多数 base64 变体可能还会=在末尾包含一个作为填充。此外,一些 base64 变体可能使用除 和 之外的字符+/请参阅维基百科上的变体摘要表以了解概述。

解决方案 2:

简短答案

您需要将bytes-like对象(bytesbytearray等)推送到该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、'+'、'/' 和 '=' 对其进行编码(某些编码使用不同的字符代替 '+' 和 '/')。这是一种基于 64 基数或 64 进制数字系统的数学构造的字符编码,但它们非常不同。数学中的 64 基数是一种类似于二进制或十进制的数字系统,您可以对整个数字执行这种基数更改,或者(如果您要转换的基数是小于 64 的 2 的幂)从右到左以块的形式执行。

base64编码中,转换是从左到右进行的;前 64 个字符就是它被称为base64 编码的原因。第 65 个 '=' 符号用于填充,因为编码提取 6 位块,但它通常要编码的数据是 8 位字节,所以有时最后一块只有 2 位或 4 位。

例子:

>>> data = b'test'
>>> for byte in data:
...     print(format(byte, '08b'), end=" ")
...
01110100 01100101 01110011 01110100
>>>

如果将该二进制数据解释为单个整数,则可以这样将其转换为十进制和 64 进制(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 但是,编码将对这些数据进行重新分组:

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 编码必须以相反的方向进行编码(因此原始数据将转换为“dGVzdA”),并且还具有一条规则来告诉其他应用程序末尾还剩下多少空间。这是通过在末尾填充“=”符号来实现的。因此,base64此数据的编码为“dGVzdA==”,其中有两个“=”符号表示在解码此数据以使其与原始数据匹配时,需要从末尾删除两对位。

让我们测试一下,看看我是否不诚实:

>>> encoded = base64.b64encode(data)
>>> print(encoded)
b'dGVzdA=='

为什么要使用base64编码?

假设我必须通过电子邮件向某人发送一些数据,例如以下数据:

>>> data = b'x04x6dx73x67x08x08x08x20x20x20'
>>> print(data.decode())
   
>>> print(data)
b'x04msgx08x08x08   '
>>>

我种下的问题是两个:

  1. 如果我尝试在 Unix 中发送该电子邮件,则电子邮件会在x04读取字符后立即发送,因为这是END-OF-TRANSMISSION(Ctrl-D) 的 ASCII,因此剩余数据将被排除在传输之外。

  2. 此外,虽然 Python 足够聪明,可以在我直接打印数据时转义所有邪恶的控制字符,但当将该字符串解码为 ASCII 时,您会发现“msg”不存在。这是因为我使用了三个BACKSPACE字符和三个SPACE字符来擦除“msg”。因此,即使我没有EOF在那里使用字符,最终用户也无法将屏幕上的文本转换为真实的原始数据。

这只是一个演示,向您展示发送原始数据有多么困难。将数据编码为 base64 格式可为您提供完全相同的数据,但格式可确保通过电子邮件等电子媒体安全发送。

解决方案 3:

如果要编码的数据包含“外来”字符,我认为你必须用“UTF-8”进行编码

encoded = base64.b64encode (bytes('data to be encoded', "utf-8"))

解决方案 4:

如果字符串是 Unicode,最简单的方法是:

import base64                                                        

a = base64.b64encode(bytes(u'complex string: ñáéíóúÑ', "utf-8"))

# a: b'Y29tcGxleCBzdHJpbmc6IMOxw6HDqcOtw7PDusOR'

b = base64.b64decode(a).decode("utf-8", "ignore")                    

print(b)
# b :complex string: ñáéíóúÑ

解决方案 5:

这里有你需要的一切:

expected bytes, not str

前导b使您的字符串成为二进制。

您使用哪个版本的 Python?2.x 还是 3.x?

编辑:有关 Python 3.x 中字符串的详细信息,请参阅http://docs.python.org/release/3.0.1/whatsnew/3.0.html#text-vs-data-instead-of-unicode-vs-8-bit

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用