普通 Python 字符串使用什么编码?

22 投票
6 回答
21734 浏览
提问于 2025-04-16 03:10

我知道Django这个框架到处都在使用Unicode字符串,而不是普通的Python字符串。那么,普通的Python字符串用的是什么编码呢?为什么不使用Unicode呢?

6 个回答

16

嘿!我想给其他答案补充一些内容,但可惜我的积分还不够,没法好好做这件事 :-(

顺便说一下,Mike Graham的帖子写得不错,建议你先看看他的内容。

这里有几点评论:

  1. 在Python 2.x中,Unicode字面量前面需要加个“u”,但在最近的2.x版本(2.6及以上)中,这个要求可以很容易地去掉。你只需要在代码里加上 from __future__ import unicode_literals
  2. 同样,ASCII只是默认的源编码。Python能够理解多种编码提示,包括emacs风格的 # -*- coding: utf-8 -*-。想了解更多信息,可以查看 PEP 0263。改变源编码会影响Unicode字面量的解释(不管它们有没有前缀,第一点提到的影响)。在Python 3中,默认的文件编码是UTF-8。
  3. 当然,Python在内部使用编码来处理Unicode字符串(在Python 3中是 str,在2.x中是 unicode),因为最终这些内容需要写入内存。理想情况下,用户是看不到这些细节的。不过,事情总会有不完美的地方,有时你可能会遇到问题,特别是当你使用一些特殊字符时,这些字符在Unicode的基本多语言平面之外。自从Python 2.2起,我们有了所谓的 版本;这两个名字指的是内部存储Unicode代码点所用的类型。宽版本使用UCS-4,它用4个字节来存储一个Unicode代码点(这意味着UCS-4的代码单元大小是4个字节,或者32位)。窄版本使用UCS-2,UCS-2只有16位,因此不能准确编码所有Unicode代码点(它类似于UTF-16,但没有代理对)。你可以通过检查 sys.maxunicode 的值来确认。如果它是 1114111,那么你使用的是宽版本(可以正确表示所有Unicode)。如果小于这个值,也不用太担心。基本多语言平面(代码点 0x00000xFFFF)满足大多数人的需求。想了解更多信息,可以查看 PEP 0261
34

在Python 2中:普通字符串(Python 2.x中的str)没有编码,它们就是原始数据。

在Python 3中:这些被称为“字节”,这个名字很准确,因为它们只是字节的序列,可以是用任何编码方式表示的文本(有几种常见的编码方式!)或者完全不是文本的数据。

如果你想表示文本,你需要使用unicode字符串,而不是字节字符串。这里的“unicode字符串”指的是Python 2中的unicode实例和Python 3中的str实例。Unicode字符串是以抽象的方式表示的unicode代码点的序列,没有具体的编码;这非常适合表示文本。

字节字符串很重要,因为在网络上传输数据或写入文件等情况下,你不能用抽象的unicode表示数据,你需要用具体的字节表示。虽然它们常常用来存储和表示文本,但这样做其实有点不太规范。

这个情况变得复杂,因为你应该通过调用encode将unicode转换为字节,通过decode将字节转换为unicode,但Python会试图自动为你处理这些,使用一个全局编码,你可以设置,默认是ASCII,这是最安全的选择。不要依赖这个自动处理,也不要把它改成更灵活的编码——在你得到字节字符串时要明确解码,如果需要把字符串发送到外部地方,就要明确编码。

3

从Python 3.0开始,所有字符串默认都是unicode格式,同时还有一种叫做bytes的数据类型(Python文档)。

Python的开发者认为使用unicode是个好主意,而在Python 2中没有广泛使用unicode,主要是为了兼容旧版本。这也会影响性能。

撰写回答