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

2025-02-14 09:50:00
admin
原创
68
摘要:问题描述:我遵循了文档中有关如何在 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大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   3998  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2749  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   85  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   96  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   83  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用