如下依次列出python2常遇到的幾個問題及講解。python
# -*- coding:utf-8 -*-正則表達式
python2默認以ASCII編碼,可是在實際編碼過程當中,咱們會用到不少中文,爲了避免使包含中文的程序報錯,也是爲了符合國際通用慣例,通常將咱們的文件編碼設置爲utf-8格式。編程
設定編碼的格式有不少種,只要第一行或者第二行的聲明符合正則表達式 "coding[:=]\s*([-\w.]+)" 便可,通常的聲明方式爲#-*- coding:utf-8 -*-。post
str = "你好" print str
運行以上代碼,程序會報錯:SyntaxError: Non-ASCII character '\xe4' in file D:/TestPython/test/111.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details。這是提示程序中有非ASCII編碼的字符。若是加上utf-8聲明,程序就不會報錯。編碼
# -*- coding:utf-8 -*- str = "你好" print str
雖然以上寫法不會報錯,可是輸出的倒是亂碼,爲何呢?這就是下面要講的內容。spa
encode和decode.net
講解編碼和解碼以前,先來說講Unicode和utf-8的關係,推薦這篇博客給你們。code
# -*- coding:utf-8 -*-
str1 = "你好"
print type(str1)
str2 = str1.decode("utf-8")
print type(str2)
str1是str類型, 經過decode轉爲了unicode類型。orm
下面看encode代碼:blog
# -*- coding:utf-8 -*- str1 = u"你好" print type(str1) str2 = str1.encode("utf-8") print type(str2)
str1是unicode類型,經過encode轉爲了str類型。
咱們再回頭看最開始留下的問題,那段代碼爲何會輸出亂碼呢。由於文件規定的編碼格式是utf-8,可是咱們print是打印到控制檯的,控制檯沒法顯示utf-8編碼格式的字符。因此咱們要轉一下格式。
# -*- coding:utf-8 -*- str = "你好" str = str.decode("utf-8") print str
不少時候編碼解碼的時候須要加ignore參數才能正確轉換,例如.encode('utf-8', 'ignore')或.decode('utf-8', 'ignore'),你們自行斟酌吧。
chardet獲取編碼格式
有些時候咱們是沒法知道字符串是什麼編碼的,好比抓取網頁時,有些是utf-8的,有些是gb2312編碼的,那咱們該怎麼獲取編碼格式並轉換爲unicode呢。這裏就介紹到一個第三方庫chardet。使用方式大概以下:
# -*- coding: utf-8 -*- import chardet str = "xxxxx" str_type = chardet.detect(str) code = str_type['encoding']
code即爲str的編碼格式。但有些人反映該方法獲得的編碼格式不許確,速度也慢。本人親測,速度確實通常,可是目前還沒遇到不許確的狀況。你們能夠斟酌使用,我這裏只是提供一個思路,若是誰那裏有更好的方式,能夠告知小弟,不吝賜教纔是。
import sys
reload(sys)
sys.setdefaultencoding('utf8')
以前也遇到過很莫名其妙的編碼錯誤,網上搜到這種方法能解決就糊里糊塗的用上了,也不知是什麼原理。今天看到一篇不錯的博客,推薦給你們:http://blog.csdn.net/crazyhacking/article/details/39375535。如下內容引用自該篇文章:
Python 裏面的編碼和解碼也就是 unicode 和 str 這兩種形式的相互轉化。編碼是 unicode -> str,相反的,解碼就是 str -> unicode。剩下的問題就是肯定什麼時候須要進行編碼或者解碼了.關於文件開頭的"編碼指示",也就是 # -*- coding: -*- 這個語句。Python 默認腳本文件都是 UTF-8 編碼的,當文件中有非 UTF-8 編碼範圍內的字符的時候就要使用"編碼指示"來修正. 關於 sys.defaultencoding,這個在解碼沒有明確指明解碼方式的時候使用。好比我有以下代碼: #! /usr/bin/env python # -*- coding: utf-8 -*- s = '中文' # 注意這裏的 str 是 str 類型的,而不是 unicode s.encode('gb18030') 這句代碼將 s 從新編碼爲 gb18030 的格式,即進行 unicode -> str 的轉換。由於 s 自己就是 str 類型的,所以 Python 會自動的先將 s 解碼爲 unicode ,而後再編碼成 gb18030。由於解碼是python自動進行的,咱們沒有指明解碼方式,python 就會使用 sys.defaultencoding 指明的方式來解碼。不少狀況下 sys.defaultencoding 是 ANSCII,若是 s 不是這個類型就會出錯。拿上面的狀況來講,個人 sys.defaultencoding 是 anscii,而 s 的編碼方式和文件的編碼方式一致,是 utf8 的,因此出錯了: UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128) 對於這種狀況,咱們有兩種方法來改正錯誤: 一是明確的指示出 s 的編碼方式 #! /usr/bin/env python # -*- coding: utf-8 -*- s = '中文' s.decode('utf-8').encode('gb18030') 二是更改 sys.defaultencoding 爲文件的編碼方式 #! /usr/bin/env python # -*- coding: utf-8 -*- import sys reload(sys) # Python2.5 初始化後會刪除 sys.setdefaultencoding 這個方法,咱們須要從新載入 sys.setdefaultencoding('utf-8') str = '中文' str.encode('gb18030') 看完以後,改爲這樣 print "<p>addr:", form["addr"].value.decode('gb2312').encode('utf-8') 成功經過.
可是這種方式用着就是彆扭,仍是儘可能本身來控制編碼,明確了編碼格式,本身寫着也踏實。
我的總結
實際編程過程當中,最好能在代碼內統一編碼格式,好比統一爲unicode,由於這樣就不用考慮編碼的問題了。到了顯示或輸出時再轉換爲存儲類型(utf-八、GBK)。
以上爲最近編寫python代碼的過程當中遇到的一些問題及總結,若是有什麼不對的地方還請你們及時回覆交流,在此謝過。