PYTHON字符编码

自作多情 提交于 2019-11-26 11:39:01

Python 的默认编码是 ASCII(编者注:Python 2.x)

>>> import sys
>>> sys.getdefaultencoding()
'ascii'

所以在 Python 源代码文件中如果不显示地指定编码的话,将出现语法错误。

#test.py
print "你好"

上面是 test.py 脚本,运行 python test.py 就会包如下错误:

File “test.py”, line 1
SyntaxError: Non-ASCII character ‘\xe4′ in file
test.py on line 1, but no encoding declared;
see http://www.python.org/ps/pep-0263.html for details

为了在源代码中支持非 ASCII 字符,必须在源文件的第一行或者第二行显示地指定编码格式:

# coding=utf-8

或者

#!/usr/bin/python
# -*- coding: utf-8 -*-

在 Python 中和字符串相关的数据类型,分别是 str、unicode 两种,他们都是 basestring 的子类,可见 str 与 unicode 是两种不同类型的字符串对象。

    basestring
      /  \ 
     /    \
   str    unicode

对于同一个汉字”好”,用 str 表示时,它对应的就是 utf-8 编码的 ‘\xe5\xa5\xbd’,而用 unicode 表示时,他对应的符号就是 u’\u597d’,与 u"好" 是等同的。需要补充一点的是,str 类型的字符串具体的编码格式是 UTF-8 还是 GBK ,还是其他格式,根据操作系统相关。比如在 Windows 系统中,cmd 命令行中显示的:

# windows终端
>>> a = '好'
>>> type(a)
<type 'str'>
>>> a
'\xba\xc3'

而在Linux系统的命令行中显示的是:

# linux终端
>>> a='好'
>>> type(a)
<type 'str'>
>>> a
'\xe5\xa5\xbd'

>>> b=u'好'
>>> type(b)
<type 'unicode'>
>>> b
u'\u597d'

不论是 Python 3.x、Java 还是其他编程语言,Unicode 编码都成为语言的默认编码格式,而数据最后保存到介质中的时候,不同的介质可有用不同的方式,有些人喜欢用 UTF-8,有些人喜欢用 GBK,这都无所谓,只要平台统一的编码规范,具体怎么实现并不关心。

输入图片说明

str与unicode的转换 那么在 Pytho n中 str 和 unicode 之间是如何转换的呢?这两种类型的字符串类型之间的转换就是靠这两个方法 decode 和 encode。

输入图片说明

#从str类型转换到unicode
s.decode(encoding)   =====>  <type 'str'> to <type 'unicode'>
#从unicode转换到str
u.encode(encoding)   =====>  <type 'unicode'> to <type 'str'>

>>> c = b.encode('utf-8')
>>> type(c)
<type 'str'>
>>> c
'\xe5\xa5\xbd'

>>> d = c.decode('utf-8')
>>> type(d)
<type 'unicode'>
>>> d
u'\u597d'

这个 ‘\xe5\xa5\xbd’ 就是 unicode u’好’通过函数 encode 编码得到的 UTF-8 编码的 str 类型的字符串。反之亦然,str 类型的 c 通过函数 decode 解码成 unicode 字符串 d 。

str(s)与unicode(s)

str(s) 和 unicode(s) 是两个工厂方法,分别返回 str 字符串对象和 unicode 字符串对象,str(s) 是 s.encode(‘ascii’) 的简写。实验:

>>> s3 = u"你好"
>>> s3
u'\u4f60\u597d'
>>> str(s3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

上面 s3 是 unicode 类型的字符串,str(s3) 相当于是执行 s3.encode(‘ascii’) ,因为”你好”两个汉字不能用 ascii 码来表示,所以就报错了,指定正确的编码:s3.encode(‘gbk’) 或者 s3.encode(“utf-8”) 就不会出现这个问题了。类似的 unicode 有同样的错误:

>>> s4 = "你好"
>>> unicode(s4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 0: ordinal not in range(128)
>>>

unicode(s4) 等效于 s4.decode(‘ascii’),因此要正确的转换就要正确指定其编码 s4.decode(‘gbk’) 或者 s4.decode(“utf-8”)。

乱码

所有出现乱码的原因都可以归结为字符经过不同编码解码在编码的过程中使用的编码格式不一致,比如:

# encoding: utf-8

>>> a='好'
>>> a
'\xe5\xa5\xbd'
>>> b=a.decode("utf-8")
>>> b
u'\u597d'
>>> c=b.encode("gbk")
>>> c
'\xba\xc3'
>>> print c
��

utf-8 编码的字符’好’占用3个字节,解码成 Unicode 后,如果再用 gbk 来解码后,只有 2 个字节的长度了,最后出现了乱码的问题,因此防止乱码的最好方式就是始终坚持使用同一种编码格式对字符进行编码和解码操作。

输入图片说明

其他技巧

对于如 unicode 形式的字符串(str类型):

s = 'id\u003d215903184\u0026index\u003d0\u0026st\u003d52\u0026sid'

转换成真正的 unicode 需要使用:

s.decode('unicode-escape')

测试:

>>> s = 'id\u003d215903184\u0026index\u003d0\u0026st\u003d52\u0026sid\u003d95000\u0026i'
>>> print(type(s))
<type 'str'>
>>> s = s.decode('unicode-escape')
>>> s
u'id=215903184&index=0&st=52&sid=95000&i'
>>> print(type(s))
<type 'unicode'>
>>>

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!