原始位置:
今天在嘗試Python的CGI模塊時遇到中文字符不能正確顯示的問題,很鬱悶.在網上仔細找了找,終於解決了這個問題,現在將解決方法陳述如下,以防下次失誤.
頁面源代碼如下
#-*- coding: utf8 -*-
import cgitb , cgi
cgitb.enable()
cgitb.enable()
form = cgi.FieldStorage()
if (form.has_key("name") and form.has_key("addr")):
print "
name:", form["name"].valueif (form.has_key("name") and form.has_key("addr")):
print "
print "
addr:", form["addr"].value
[這裡僅僅測試addr參數為中文]接收Ascii字符時運行良好,但是接收中文字符時顯示亂碼,瀏覽器切換到GB2312編碼時
可以正常顯示,但是個人要求它成為UTF-8編碼顯示
改成print "
addr:", form["addr"].value.encode('utf-8') 就報如下錯誤:
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-1: invalid data
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')
是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 "
addr:", form["addr"].value.decode('gb2312').encode('utf-8')成功通過.
我總結一下為什麼要這麼寫的原因 :
1. 當取回來的數據與你當前腳本中聲明的編碼不一致時就要做編碼轉換
2.在編碼轉換時首先要將該數據以自身編碼的格式換成unicode碼,再將這個unicode按utf8編碼
3.為什麼我的瀏覽器會傳回gb2312 的編碼數據到服務器,這應該和客戶端的系統編碼有關係
這裡順便轉載一下,關於Python 操作Mysql的中文問題:
Python操作MySQL以及中文亂碼的問題
下面幾個措施,保證MySQL的輸出沒有亂麻:1 Python文件設置編碼utf-8 (文件前面加上#encoding=utf-8) 2 MySQL數據庫charset=utf-8 3 Python連接MySQL是加上參數charset= utf8 4設置Python的默認編碼為utf-8 (sys.setdefaultencoding(utf-8)
- #encoding=utf- 8
- import sys
- import MySQLdb
- reload(sys)
- sys.setdefaultencoding( 'utf-8' )
- db=MySQLdb.connect(user= 'root' ,charset= 'utf8' )
- cur=db.cursor()
- cur.execute( 'use mydb' )
- cur.execute( 'select * from mytb limit 100' )
- f=file( "/home/user/work/tem.txt" , 'w' )
- for i in cur.fetchall():
- f.write(str(i))
- f.write( " " )
- f.close()
- cur.close()
測試以下連接成功: index.psp?name=iamsese&addr=北京
沒有留言:
張貼留言