Python-編碼這趟渾水
最近聽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-編碼這趟渾水