1. 程式人生 > >Python-編碼這趟渾水

Python-編碼這趟渾水

byte utf-8 ini href 通過 簡單的 轉化 常見 print

最近聽Alex講到python編碼,還特意用博客講解,覺得問題嚴重了,於是翻看各種博客,先簡單的對編碼錯誤做一個總結,其他的後續慢慢補上,還得上班、還得學習、還得寫博客?感覺有點吃不消了。各位大神不喜勿噴啊。本人是Mac電腦,終端默認編碼格式utf-8

原文地址

Python編碼錯誤及解決辦法

字符串是python中最常用的數據類型,而且很多時候會用一些不屬於ascii字符集的字符,這是就會拋出UnicodeDecodeError:ascii codec can‘t decode byte 0xc4 in position 10:oridinal not range(128)異常。這種異常在python中很容易遇到,尤其是在python2.x中

字符串在python內部的表示是unicode編碼,因此,在做編碼轉換是,通常需要以unicode作為轉碼的中間編碼,即先將其他編碼的字符串解碼(decode)成unicode,再從unicode編碼(encode)成另一種編碼。但是在Python2.x中默認編碼格式是ascii,就是說在沒有指定Python源碼編碼格式的情況下,源碼中所有字符都被默認為ascii碼。也是因為這個根本原因,在Python2.x中經常遇到UnicodeDecodeError或者UnicodeEncodeError的異常。

Unicode為了能夠處理Unicode數據,同時兼容Python某些內部模塊,Python2.x中提供了Unicode這種數據類型,通過decode和encode方法可以將其他編碼和unicode編碼相互轉換。

Python常見編碼異常(幾乎都出現在Python2.x中)

Python中常見的編碼異常包括:SyntaxError: Non-ASCII character 、UnicodeDecodeError和UnicodeEncodeError等。

1.SyntaxError: Non-ASCII character

這種異常不是很常見,但最好解決了。只要是因為Python源碼文件中存在不屬於ascii字符,而且同時沒有聲明源碼的編碼格式,例如

#在Python2.x中,在文件頭部沒有指定編碼格式

s = 土耳其大騙子
print  s

#SyntaxError: Non-ASCII character ‘\xe5‘ in file /xxx/xxx/exercise-unicode.py on line 2, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

解決辦法:在文件頭部聲明編碼格式 #!-*- encoding:utf-8 -*-或#!encoding:utf-8

Python2.x中如果不在源碼文件首行指定編碼格式,則無法在Python源碼文件中出現非ascii字符。這是由於Python解釋器默認將源碼認為是ascii編碼格式

2.UnicodeDecodeError

這個異常則會出現在調用decode方法時,原因是Python將其他編碼格式的字符轉化為unicode編碼,但是字符本身的編碼格式和decode傳入的編碼格式不一致,例如:


#Python2.x中
#!encoding:utf-8
s = 土耳其大騙子 us = s.decode(gbk) #異常 #UnicodeDecodeError: ‘gbk‘ codec can‘t decode bytes in position 4-5: illegal multibyte sequence

上面這段代碼字符串字符串s默認的編碼格式是“utf-8”(#!encoding:utf-8聲明的意思就是:當前.py文件中所有的字符都是utf-8編碼的),但是在使用decode轉化為unicode編碼是傳入的編碼格式為“gbk”,因此在轉化的時候拋出UnicodeDecodeError異常。還有一種情況是在encode的時候:

#Python2.x中
#! -*- encoding:utf-8 -*-

s = 土耳其大騙子
us = s.encode(gbk)

#輸出
#UnicodeDecodeError: ‘ascii‘ codec can‘t decode byte 0xe5 in position 0: ordinal not in range(128)

這裏是s是“utf-8”編碼,直接使用s.encode(‘gbk‘),實際上是使用了系統默認的defaultencoding來解碼,等價於

s.decode(defaultencoding).encode(gbk)

而s的實際編碼和defaultencoding(python2.x默認是ascii)不同。

3.UnicodeEncodeError

錯誤的decode和encode方法會出現異常,比如使用decode方法將unicode字符串轉化的時候

#! -*- encoding:utf-8 -*-

s = u土耳其大騙子
us = s.decode(utf-8)

#輸出
#UnicodeEncodeError: ‘ascii‘ codec can‘t encode characters in position 0-5: ordinal not in range(128)

由於在Python2.x中,字符串轉化為unicode編碼的時候,可以通過unicode(‘xxx‘)、u‘xxx‘、‘xxx‘.decode(‘utf-8‘),但是本示例是將unicode編碼的字符串解碼,於是拋出“UnicodeEncodeError”異常

Python中編碼規範

1.遵循PEP0263原則,聲明編碼格式(推薦)

在PEP 0263 Defining Python Source Code Encodings中提出了對Python編碼問題的最基本的解決方法:在Python源碼文件中聲明編碼格式,最常見的聲明格式如下:

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

表示當前.py文件的字符串編碼格式都是按照“utf-8”編碼的,不是讀取的文件是用“utf-8”編碼讀取的

2.使用 u‘中文‘ 代替中文(Python 2.x)

s1 = ‘中文‘
s2 = u中文

Python中有以上兩種聲明字符串變量的方式,它們的主要的是編碼格式的不同,其他s1的編碼格式和Python頭文件聲明的編碼格式一致,而s2的編碼格式則是unicode。如果你聲明的字符串變量中包含非ascii字符,最好使用s2的的聲明格式,這樣你可以不需要執行decode,直接對字符串進行操作,可以避免出現一個異常。

註意:Python3中不存在 u‘xx‘的聲明方式。

3.Reset默認編碼

Python中出現這麽多的編碼問題的根本原因是Python 2x中的默認編碼是ascii,所以你可以通過以下的方式修改默認的編碼格式:

import sys
sys.setdefaultencoding(utf-8)

這種方法可以解決部分編碼問題,但是同時也會引入很多其他問題,得不償失,建議不要使用這種方式。

Python-編碼這趟渾水