【转】python编码的问题

摘要:

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

# coding=utf-8

或者是:

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

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

    basestring
/ \
/ \
str unicode

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

【转】python编码的问题

str与unicode的转换

那么在Python中str和unicode之间是如何转换的呢?这两种类型的字符串类型之间的转换就是靠这两个方法decodeencode

【转】python编码的问题

#从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个字节的长度了,最后出现了乱码的问题,因此防止乱码的最好方式就是始终坚持使用同一种编码格式对字符进行编码和解码操作。

【转】python编码的问题

转自:

PYTHON编码的前世今生-原文

Python编码的前世今生-微信

上一篇:Serverless For Frontend 个人理解与解惑


下一篇:C++ Primer 阅读笔记:迭代器和容器 小结