1. python2的默認編碼是ascii,python3的默認編碼是utf-8python
Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:24:40) [MSC v.1500 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.getdefaultencoding() 'ascii' Python 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import sys >>> sys.getdefaultencoding() 'utf-8'
2. 常見編碼狀況linux
print sys.getdefaultencoding() #系統默認編碼 print sys.getfilesystemencoding() #文件系統編碼 print locale.getdefaultlocale() #系統當前編碼 print sys.stdin.encoding #終端輸入編碼 print sys.stdout.encoding #終端輸出編碼
window終端輸出windows
ascii mbcs ('zh_CN', 'cp936') cp936 cp93
linux終端輸出bash
ascii UTF-8 ('zh_CN', 'UTF-8') UTF-8 UTF-8
3. python str->unicode是decode,unicode->str是encode,見下圖函數
>>> import sys >>> sys.getdefaultencoding() 'ascii' >>> a='強' # str字符串 >>> b=u'強' # unicode字符串 >>> print isinstance(a, str) True >>> print isinstance(b, unicode) True # 由於只有unicode纔有encode方法,此處python會作默認轉換,也即a.decode('ascii').encode('utf-8') # 會獲取默認編碼ascii轉換中文字符,固然錯誤,報UnicodeDecodeError >>> a.encode('utf-8') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xc7 in position 0: ordinal not in range(128) # 指定utf-8再轉換就會正確解析,結果unicode字符串,注意u'\u01ff'前面的u,觀察這個便可知道當前是unicode or 二進制字節碼 >>> a.decode('utf-8') u'\u01ff' # 不需轉換,顯示二進制字節碼 >>> str(a) '\xc7\xbf' # b是unicode類型,需轉化爲str類型,b.encode('ascii')報錯 >>> str(b) Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeEncodeError: 'ascii' codec can't encode character u'\u5f3a' in position 0: ordinal not in range(128) # unicode沒有decode,需轉爲str,b.encode('ascii'),轉化時出錯 >>> b.decode('utf-8') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Python27\lib\encodings\utf_8.py", line 16, in decode return codecs.utf_8_decode(input, errors, True) UnicodeEncodeError: 'ascii' codec can't encode character u'\u5f3a' in position 0: ordinal not in range(128) # 指定編碼正確轉換 >>> b.encode('utf-8') '\xe5\xbc\xba' >>>
4. python進行同時包含str和unicode的運算時(+,%等),一概轉爲unicode處理,固然結果也是unicodeui
>>> a='強' # str字符串 >>> b=u'強' # unicode字符串 # 這裏str和unicode運算,所有轉化爲unicode,str轉unicode時用ascii轉換,固然報錯 >>> a+b Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xc7 in position 0: ordinal not in range(128) # 此處都是str不用轉,正確 >>> '強%s' % a '\xc7\xbf\xc7\xbf' # 此處b是unicode,至關於'強%s'.decode('ascii') % b, 因此錯誤 >>> '強%s' % b Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xc7 in position 0: ordinal not in range(128) # 反過來也是同樣的 >>> u'強%s' % a Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xc7 in position 0: ordinal not in range(128) >>> u'強%s' % b u'\u5f3a\u5f3a'
5. 以上都是默認ascii編碼致使的,那麼設置下python默認編碼就能夠了編碼
>>> import sys >>> sys.setdefaultencoding('utf-8') Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'module' object has no attribute 'setdefaultencoding' # 注意須要reload下 >>> reload(sys) <module 'sys' (built-in)> >>> sys.setdefaultencoding('utf-8') >>> sys.getdefaultencoding() 'utf-8' >>> a='強' # str字符串 >>> b=u'強' # unicode字符串 # 再進行以上操做,都正確了 >>> a+b u'\u01ff\u5f3a' >>> '強%s' % a '\xc7\xbf\xc7\xbf' >>> '強%s' % b u'\u01ff\u5f3a' >>> u'強%s' % a u'\u5f3a\u01ff' >>> u'強%s' % b u'\u5f3a\u5f3a' >>> a.encode('utf-8') '\xc7\xbf' >>> b.decode('utf-8') u'\u5f3a' >>> str(a) '\xc7\xbf' >>> str(b) '\xe5\xbc\xba'
6. python文件默認編碼也是ascii,假若有中文就會報錯以下code
假若有t.py文件,裏面有非ascii字符orm
# file t.py a='夏天'
執行時會報錯utf-8
E:/>python t.py File "t.py", line 1 SyntaxError: Non-ASCII character '\xcf' in file t.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
在頭部加入,指定源代碼編碼格式
# -*- coding: utf-8 -*- 或者 #coding=utf-8
聲明下默認編碼便可
7. 如文件編碼爲ANSI的,裏面有中文的unicode定義,也會報錯
t.py
#coding=utf-8 a='夏天' b=u'秋天'
執行也會報錯
E:\>python t.py File "t.py", line 3 b=u'秋天' SyntaxError: (unicode error) 'utf8' codec can't decode byte 0xc7 in position 0: invalid continuation byte
把文件編碼改成UTF-8便可解決
8. print, 終端亂碼
print和終端相關,會根據sys.stdin.encoding, sys.stdout.encoding來處理,若是輸出的字符串和終端編碼不同就會亂碼
t.py
#! -*- coding:utf-8 -*- a='中文' print a print type(a)
windows下
E:\>python t.py 涓枃 <type 'str'>
linux下
# python t.py 中文 <type 'str'>
由於windos控制檯編碼爲cp936編碼即gbk編碼,而變量a自己編碼爲utf-8
那麼定義的unicode字符如何呢,見下面
#! -*- coding:utf-8 -*- a='中文' print a # 涓枃 print type(a) # <type 'str'> b=a.decode('utf-8') print b # 中文 b=u'中文' print b # 中文 print type(b) # <type 'unicode'> print b.encode('gbk') # 中文 str(b) # UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
可見,unicode的字符print正常,按gbk encode->str時也正常,爲何呢
可這樣簡單理解,print輸出到終端時,要是str,若是str的編碼與終端編碼不一致,那麼亂碼
若是不是str,則須要轉爲str,這個是獲取終端編碼,也即python替你作了, encode('gbk')
但str(b)咋又報錯了呢,這是由於,str是python內建函數,會獲取getdefaultencoding,而這個編碼是ascii,因此報錯
再進一步,加入重定向到文件呢
#! -*- coding:utf-8 -*- b=u'中文' print b
python t.py > result
會報錯UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
由於輸出到控制檯時,print 使用的是控制檯的默認編碼,而重定向到文件時,print 就不知道使用什麼編碼了,因而就使用了默認編碼 ascii 致使出現編碼錯誤。這時咱們就不該該讓python幫咱們作,咱們本身指定
#! -*- coding:utf-8 -*- b=u'中文' print b.encode('utf-8')
這樣就會正常
9. write
#! -*- coding:utf-8 -*- with open('ttt.txt', 'w') as f: f.write('test') # 正常寫入 f.write('夏天') # 正常寫入 #f.write(u'秋天') # 錯誤,因爲是unicode,python要轉換爲str再寫入,encode時用的ascii,觸發UnicodeEncodeError異常 f.write(u'秋天'.encode('utf-8')) # 寫入正常,unicode->str
或者指定默認編碼,這樣就不用手動encode了,見下
#! -*- coding:utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8') with open('ttt.txt', 'w') as f: f.write('test,') # 正常寫入 f.write('夏天,') # 正常寫入 f.write(u'秋天,') # 寫入正常
10. read
#! -*- coding:utf-8 -*- import sys reload(sys) sys.setdefaultencoding('utf-8') with open('ttt.txt', 'w') as f: f.write('test,') # 正常寫入 f.write('夏天,') # 正常寫入,亂碼 f.write(u'秋天,') # 寫入錯誤,因爲是unicode,python要轉換爲str再寫入,encode時用的ascii,觸發UnicodeEncodeError異常 #f.write(u'秋天'.encode('utf-8')) # 寫入正常,unicode->str with open('ttt.txt') as f: for line in f: print line, type(line) # test澶忓ぉ縐嬪ぉ <type 'str'> line2 = line.decode('utf-8') print line2, type(line2) # test夏天秋天 <type 'str'> print '-----------------------------' # 經過io包下的open打開文件可設置編碼 from io import open with open('ttt.txt', encoding='utf-8') as f: for line in f: print line, type(line) # test夏天秋天 <type 'unicode'> # 由上可見,內建函數open,不能指定編碼,其按客戶端所在編碼解碼,line類型是str # io.open可指定編碼,同時line讀取類型爲unicode
建議措施:
以上全部其實就是在不一樣地方python默認轉換時採用的編碼和咱們設置的編碼不一致致使的,因此分析時先分析當前python應該獲取什麼編碼,而後再分析。好比,str(..) 會獲取getdefaultencoding,print會獲取sys.stdout.encoding等
1. 牽扯到中文的地方,都聲明頭部編碼,同時文件編碼設爲utf-8
# -*- coding: utf-8 -*- 或者 #coding=utf-8
2. 同時設置sys 默認編碼
import sys reload(sys) sys.setdefaultencoding('utf-8')
3. python代碼內部請所有使用unicode編碼,在獲取外部內容時,先decode爲unicode,向外輸出時再encode爲str
4. 在定義變量或者正則時,也定義unicode字符,如a=u」中文」;res=r」」+u」正則」。