普通 Python 字符串使用什么编码?
我知道Django这个框架到处都在使用Unicode字符串,而不是普通的Python字符串。那么,普通的Python字符串用的是什么编码呢?为什么不使用Unicode呢?
6 个回答
嘿!我想给其他答案补充一些内容,但可惜我的积分还不够,没法好好做这件事 :-(
顺便说一下,Mike Graham的帖子写得不错,建议你先看看他的内容。
这里有几点评论:
- 在Python 2.x中,Unicode字面量前面需要加个“u”,但在最近的2.x版本(2.6及以上)中,这个要求可以很容易地去掉。你只需要在代码里加上
from __future__ import unicode_literals
。 - 同样,ASCII只是默认的源编码。Python能够理解多种编码提示,包括emacs风格的
# -*- coding: utf-8 -*-
。想了解更多信息,可以查看 PEP 0263。改变源编码会影响Unicode字面量的解释(不管它们有没有前缀,第一点提到的影响)。在Python 3中,默认的文件编码是UTF-8。 - 当然,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)。如果小于这个值,也不用太担心。基本多语言平面(代码点0x0000
到0xFFFF
)满足大多数人的需求。想了解更多信息,可以查看 PEP 0261。
在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,这是最安全的选择。不要依赖这个自动处理,也不要把它改成更灵活的编码——在你得到字节字符串时要明确解码,如果需要把字符串发送到外部地方,就要明确编码。
从Python 3.0开始,所有字符串默认都是unicode格式,同时还有一种叫做bytes的数据类型(Python文档)。
Python的开发者认为使用unicode是个好主意,而在Python 2中没有广泛使用unicode,主要是为了兼容旧版本。这也会影响性能。