<p>好吧,我想我要总结一下我目前对事物的理解(请随意纠正我)。希望它能帮助其他人,就像我一样困惑。</p>
<p>当然,功劳完全归于<a href="https://stackoverflow.com/users/75103/thebjorn">thebjorn</a>和<a href="https://stackoverflow.com/users/395760/delnan">delnan</a>。</p>
<p>所以,从最常见的事情开始:
这里有<a href="http://en.wikipedia.org/wiki/Unicode" rel="nofollow noreferrer">Unicode</a>,它是一个全球标准,为所有你能想象到的外来字符分配代码(或代码点)。这些代码只是整数。维基百科称,截至Unicode 6.1,共有109975个图形字符。</p>
<p>还有一些编码定义了如何用字节码指定Unicode字符。一个字节不足以指定任意Unicode字符。尽管如此,如果只取其中的一小部分(英文字母表、数字、标点符号、一些控制字符),每个字符只需一个字节(甚至7位;请参见<a href="http://en.wikipedia.org/wiki/ASCII" rel="nofollow noreferrer">ASCII</a>)。</p>
<hr/>
<p>要在任何地方传递Unicode字符串,需要对其进行字节编码,然后在另一端进行解码。</p>
<p>在Python 2中,<code>str</code>实际上是字节,<code>unicode</code>是Unicode,但是python2会在需要时为您执行隐式编码/解码。它将尝试使用ASCII编码。</p>
<p>在Python 3中,<code>str</code>始终是Unicode字符串,<code>bytes</code>是实际字节的新数据类型。Python 3从不进行隐式转换,您始终需要自己进行转换并指定编码。这意味着你的程序只有在你了解发生在我身上的事情后才能运行。</p>
<hr/>
<p>现在,这或多或少是清楚的,让我们转到<a href="http://en.wikipedia.org/wiki/Base64" rel="nofollow noreferrer">base64</a>编码,这也是一种分类编码,但有一个稍微不同的含义。
假设您有一些二进制数据(即<em>字节</em>),它们可能意味着任何东西(在我的例子中是一堆<code>float</code>)。现在要用字符串表示这个二进制数组。这就是base64编码的含义:您的字节被表示为ASCII字符串。</p>
<p>Base64表示6位,因此在Base64编码的字符串中,单个字符代表6位数据。这就是为什么base64编码字符串的长度必须是4的倍数:否则编码的字节数将不是整数。</p>
<hr/>
<p>最后,要从base64解码,需要一个ASCII字符串。Unicode字符串不行,只能有base64字母表中的字符。<a href="http://docs.python.org/py3k/library/base64.html" rel="nofollow noreferrer">Base64 module</a>在Python中完成任务。<code>base64.b64decode()</code>函数接受一个字节字符串作为参数。在Python 2中,它的意思是:<code>str</code>。在Python 3中,它的意思是:<code>bytes</code>。所以如果你有一个<code>str</code>,比如</p>
<pre><code>>>> s = 'U3RhY2sgT3ZlcmZsb3c='
</code></pre>
<p>在Python 2中,您可以</p>
<pre><code>>>> s.decode('base64')
</code></pre>
<p>因为<code>s</code>已经是ASCII格式。
在Python 3中,首先需要用ASCII编码,所以必须:</p>
<pre><code>>>> base64.b64decode(s.encode('ascii'))
</code></pre>
<p>顺便说一下,这将返回一个<code>bytes</code>对象,所以如何处理这些字节真的取决于您。也许这是我的浮动,但也许你应该尝试将其解码为ASCII:)
然而,在Python 2中,它只是一个<code>str</code>。无论如何,请查看<a href="http://docs.python.org/library/struct.html" rel="nofollow noreferrer">^{<cd13>}</a>以获得从这些字节解包数据的工具。</p>
<p>因此,如果需要在Python 2和3上运行代码,请使用最后一个。要确保最后有Unicode(如果要从base64解码文本),必须对其进行解码:</p>
<pre><code>>>> base64.b64decode(s.encode('ascii')).decode('ascii')
</code></pre>
<p>在Python 2上,<code>encode('ascii')</code>不会有效地执行任何操作,因为它应用于<code>str</code>。因此,它将首先执行<em>隐式转换</em>到Unicode,然后执行所需的操作(将其转换回ASCII)。<code>decode('ascii')</code>将在Python 2上返回一个<code>unicode</code>对象。</p>