在python 3中解码base64字符串(是否使用lxml)

2024-09-28 22:31:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道这看起来很简单,我想问题是我对所有这些字节str unicode(和编码解码,坦率地说)还没有一个清晰的理解。

我一直在尝试让我的工作代码在Python 3上运行。我遇到的问题是当我用lxml解析一个XML并解码该XML中的base64字符串时。

代码现在按以下方式工作:

我使用XPath查询'.../binary/text()'检索二进制数据。这将生成一个包含lxml.etree._ElementUnicodeResult对象的单元素列表。然后,使用python 2,我能够:

decoded = source.decode('base64')

最后

output = numpy.frombuffer(decoded)

但是,在python 3上,我得到一条错误消息,说

AttributeError: 'lxml.etree._ElementUnicodeResult' object has no attribute 'decode'

这并不奇怪,因为lxml.etree._ElementUnicodeResultstr的一个子类。

另一种方法是使用

 binary = tree.xpath('//binary')[0]
 binary_string = binary.text

这基本上是一样的。那么我该怎么从base64解码呢?我已经看过base64模块,但是它接受一个bytes对象作为参数,我想不出将str表示为bytes的方法,因为如果我尝试构造一个bytes对象,Python将尝试对字符串进行编码,这是我不需要的。

进一步搜索,我发现了binascii模块(如果我没有弄错的话,它是从base64间接调用的),但是对我的字符串调用binascii.b2a_base64()会产生

TypeError: 'str' does not support the buffer interface

另外,我甚至在how to decode a hex string in Python 3上找到了一个答案,但是这是用一个专用的方法完成的,所以我看不出它有什么帮助。

有人能告诉我我缺了什么吗?恐怕大部分帖子都无关紧要,只会加重我的羞耻感,但至少你们知道what I tried


Tags: 对象方法字符串代码编码bytesxml解码
2条回答

我没有安装Python3,但听起来您需要将从lxml返回的Unicode转换为字节,也许可以通过调用.encode('ascii')?

好吧,我想我要总结一下我目前对事物的理解(请随意纠正我)。希望它能帮助其他人,就像我一样困惑。

当然,功劳完全归于thebjorndelnan

所以,从最常见的事情开始: 这里有Unicode,它是一个全球标准,为所有你能想象到的外来字符分配代码(或代码点)。这些代码只是整数。维基百科称,截至Unicode 6.1,共有109975个图形字符。

还有一些编码定义了如何用字节码指定Unicode字符。一个字节不足以指定任意Unicode字符。尽管如此,如果只取其中的一小部分(英文字母表、数字、标点符号、一些控制字符),每个字符只需一个字节(甚至7位;请参见ASCII)。


要在任何地方传递Unicode字符串,需要对其进行字节编码,然后在另一端进行解码。

在Python 2中,str实际上是字节,unicode是Unicode,但是python2会在需要时为您执行隐式编码/解码。它将尝试使用ASCII编码。

在Python 3中,str始终是Unicode字符串,bytes是实际字节的新数据类型。Python 3从不进行隐式转换,您始终需要自己进行转换并指定编码。这意味着你的程序只有在你了解发生在我身上的事情后才能运行。


现在,这或多或少是清楚的,让我们转到base64编码,这也是一种分类编码,但有一个稍微不同的含义。 假设您有一些二进制数据(即字节),它们可能意味着任何东西(在我的例子中是一堆float)。现在要用字符串表示这个二进制数组。这就是base64编码的含义:您的字节被表示为ASCII字符串。

Base64表示6位,因此在Base64编码的字符串中,单个字符代表6位数据。这就是为什么base64编码字符串的长度必须是4的倍数:否则编码的字节数将不是整数。


最后,要从base64解码,需要一个ASCII字符串。Unicode字符串不行,只能有base64字母表中的字符。Base64 module在Python中完成任务。base64.b64decode()函数接受一个字节字符串作为参数。在Python 2中,它的意思是:str。在Python 3中,它的意思是:bytes。所以如果你有一个str,比如

>>> s = 'U3RhY2sgT3ZlcmZsb3c='

在Python 2中,您可以

>>> s.decode('base64')

因为s已经是ASCII格式。 在Python 3中,首先需要用ASCII编码,所以必须:

>>> base64.b64decode(s.encode('ascii'))

顺便说一下,这将返回一个bytes对象,所以如何处理这些字节真的取决于您。也许这是我的浮动,但也许你应该尝试将其解码为ASCII:) 然而,在Python 2中,它只是一个str。无论如何,请查看^{}以获得从这些字节解包数据的工具。

因此,如果需要在Python 2和3上运行代码,请使用最后一个。要确保最后有Unicode(如果要从base64解码文本),必须对其进行解码:

>>> base64.b64decode(s.encode('ascii')).decode('ascii')

在Python 2上,encode('ascii')不会有效地执行任何操作,因为它应用于str。因此,它将首先执行隐式转换到Unicode,然后执行所需的操作(将其转换回ASCII)。decode('ascii')将在Python 2上返回一个unicode对象。

相关问题 更多 >