【整理】Python中實際上已經得到了正確的Unicode或某種編碼的字符,但是看起來或打印出來卻是亂碼


轉自:http://www.crifan.com/python_already_got_correct_encoding_string_but_seems_print_messy_code/

 

 

 

【背景】

Python中的字符編碼,其實的確有點復雜。

再加上,不同的開發環境和工具中,顯示的邏輯和效果又不太相同,尤其是,中文的,初級用戶,最常遇到的:

(1)在Python自帶的IDE:IDLE中折騰中文字符,結果看到的差不多都是亂碼類的東西,比如:’\xd6\xd0\xce\xc4′

(2)將一個中文字符,打印輸出到windows的cmd命令行中,看到的是亂碼

對此,此處專門整理一下,這些常見的現象,和現象背后的根本原因,以及如何解決這類問題。

 

背景知識

其實,看下面問題之前,最好是已經了解相關的背景知識,才更容易看懂的:

1.字符編碼的基本知識

對於字符編碼本身,比如UTF-8,GBK等等,不熟悉的,不了解是啥的話,先去看:

字符編碼詳解

 

2.Windows的cmd中的默認是GBK編碼

這方面不了解的,也需要先去看:

Windows的命令行工具: cmd

中的:

設置字符編碼:簡體中文GBK/英文

 

3.關於IDLE

其實也要先大概了解:

Python內部,默認的字符編碼是,是根據操作系統,我們多數都是Windows的中文系統,默認是GBK編碼。

而IDLE中,直接輸入中文字符,其實就是GBK編碼的。

 

4.Python中的字符串的設計

主要是:Python 2.x中的str和unicode ,和,Python 3.x中的bytes和str,之間的邏輯,轉換,和區別。

不了解的,也要先去看:

【整理】Python中字符編碼的總結和對比:Python 2.x的str和unicode vs Python 3.x的bytes和str

 

常見問題:IDLE中看到類似於’\xd6\xd0\xce\xc4’,而不是我想要的中文字符

初學者,最容易遇到的問題就是:

中文用戶,用了Python自帶的IDLE,在里面輸入中文后,結果顯示出,類似於:

‘\xce\xd2\xca\xc7\xd6\xd0\xce\xc4’

的內容,而不是希望看到輸出的中文字符,比如:

input cn char show slash x num

此現象的解釋是:

實際上,此處你,本身就已經得到了,正確的,默認的GBK編碼的,中文字符串:"我是中文"

了。只是:

IDLE這個,Python自帶的IDE,不是很好用的IDE,給你顯示出來,其內部的16進制的值而已。

1. 對於此點,你可以去用decode去驗證一下:

Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32 
Type "copyright", "credits" or "license()" for more information. 
>>> "我是中文" 
‘\xce\xd2\xca\xc7\xd6\xd0\xce\xc4’ 
>>> "我是中文".decode("GBK") 
u’\u6211\u662f\u4e2d\u6587′ 
>>>

can use decode to verify gbk cn char

其中,GBK的字符串,經過解碼后,就可以得到Unicode的字符串了,對應的顯示出來的是:

u’\u6211\u662f\u4e2d\u6587′

此處的:

\u6211,\u662f,\u4e2d,\u6587,分別對應着,四個中文字符:"我","是","中","文"

2. 有人會問,我怎么知道這些值,是對應着這四個中文字符的呢?

答案是:

那是因為你不熟悉Unicode。且也不會去查Unicode表格。

等你看了之前告訴你的:

字符編碼詳解

然后再去參考我的:

HTML相關的參考資料

去查Unicode值,就可以查到“我”對應的Unicode值是0x6211:

me in unicode is 0x6211

同理,可以查得剩下的:

0x662f="是"=\u662f

0x4e2d="中"=\u4e2d

0x6587="文"=\u6587

3.回到上面的問題,接着,還可以接着進一步驗證,之前的字符串,的確是GBK:

Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32 
Type "copyright", "credits" or "license()" for more information. 
>>> "我是中文" 
‘\xce\xd2\xca\xc7\xd6\xd0\xce\xc4’ 
>>> "我是中文".decode("GBK") 
u’\u6211\u662f\u4e2d\u6587′ 
>>> "我是中文".decode("GBK").encode("GBK") 
‘\xce\xd2\xca\xc7\xd6\xd0\xce\xc4’

previous is gbk decoed to same gbk

即:

之前直接輸入中文字符所得到的16進制值,和通過GBK解碼后得到Unicode,然后再編碼為GBK的16進制的值,是一樣的

-> 說明之前的中文字符的確是GBK的編碼。

4.另外,也可以順帶看看,UTF-8的輸出是啥:

Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32 
Type "copyright", "credits" or "license()" for more information. 
>>> "我是中文" 
‘\xce\xd2\xca\xc7\xd6\xd0\xce\xc4’ 
>>> "我是中文".decode("GBK") 
u’\u6211\u662f\u4e2d\u6587′ 
>>> "我是中文".decode("GBK").encode("GBK") 
‘\xce\xd2\xca\xc7\xd6\xd0\xce\xc4’ 
>>> "我是中文".decode("GBK").encode("UTF-8") 
‘\xe6\x88\x91\xe6\x98\xaf\xe4\xb8\xad\xe6\x96\x87’

see the cn char utf8 value

 

所以,總結此問題:

IDLE中輸入中文字符,但是顯示出來的是類似於’\xd6\xd0\xce\xc4’的值,而不是想要的中文字符

的答案就是:

其實本身已經是中文字符。

只是根據當前默認是GBK編碼,所顯示出來的GBK編碼的內部的值而已。

 

其實,對此問題,更加終極的解決辦法是:

由於IDLE不是很好用,所以不推薦用戶,尤其是初學者,直接就用IDLE來開發Python。

而是推薦你用:

Notepad++ 加 cmd

具體的原因和解釋,詳見:

【整理】【多圖詳解】如何在Windows下開發Python:在cmd下運行Python腳本,如何使用Python Shell(command line模式和GUI模式),如何使用Python IDE

 

更更終極的辦法是:

這類常見的錯誤,屬於學習Python中所容易走的彎路。

而你要是按照我的教程去學習,不僅可以少走很多彎路,而且更容易明白很多基本的邏輯:

初級的:

python初級教程:入門詳解

中級的:

python中級教程:開發總結

高級專題闡述:

Python專題教程:字符串和字符編碼

Python專題教程:抓取網站,模擬登陸,抓取動態網頁

 

常見問題:中文字符打印輸出顯示到命令行(Windows的cmd)顯示亂碼

和上面的現象類似的一個現象就是:

當用python代碼,打印輸出一個中文字符到命令中,結果卻顯示亂碼。

(1)用如下代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------------------------------------
[Function]
【整理】Python中實際上已經得到了正確的Unicode或某種編碼的字符,但是看起來或打印出來卻是亂碼
 
[Date]
2013-07-19
 
[Author]
Crifan Li
 
[Contact]
-------------------------------------------------------------------------------
"""
  
#---------------------------------import---------------------------------------
 
#------------------------------------------------------------------------------
def char_ok_but_show_messy():
     """
         Demo Python already got normal chinese char, with some encoding, but print to windows cmd show messy code
     """
     #此處,當前Python文件是UTF-8編碼的,所以如下的字符串,是UTf-8編碼的
     cnUtf8Char = "我是UTF-8的中文字符串" ;
     #所以,將UTF-8編碼的字符串,打印輸出到GBK編碼的命令行(Windows的cmd)中,就會顯示出亂碼
     print  "cnUtf8Char=" ,cnUtf8Char; #cnUtf8Char= 鎴戞槸UTF-8鐨勪腑鏂囧瓧絎︿覆
     #如果想要正確顯示出中文字符,不顯示亂碼的話,則有兩種選擇:
     #1. 把字符串轉換為Unicode編碼,則輸出到GBK的命令行時,Python會自動將Unicode的字符串,編碼為GBK,然后正確顯示字符
     decodedUnicodeChar = cnUtf8Char.decode( "UTF-8" );
     print "decodedUnicodeChar=" ,decodedUnicodeChar; #decodedUnicodeChar= 我是UTF-8的中文字符串
     #2. 讓字符串的編碼和輸入目標(windows的cmd)的編碼一致:把當前的字符串(由上述解碼后得到的Unicode再次去編碼)也變成GBK,然后輸出到GBK的命令行時,就可以正確顯示了
     reEncodedToGbkChar = decodedUnicodeChar.encode( "GBK" );
     print "reEncodedToGbkChar=" ,reEncodedToGbkChar; #reEncodedToGbkChar= 我是UTF-8的中文字符串
    
 
###############################################################################
if __name__ = = "__main__" :
     char_ok_but_show_messy();

 

注意:

此時Python的文件編碼是UTF-8。

不了解的,詳見:

【整理】Python中用encoding聲明的文件編碼和文件的實際編碼之間的關系

(2)當前代碼下載(右鍵另存為):

char_ok_but_show_messy.py

(3)還原現象

運行的結果是:

got ok char but show messy run out

 

(4)解釋

代碼中已經解釋的很清楚了。

不再啰嗦。

 

相關帖子

和此類的,python的字符串編碼方面的相關內容,之前有更多的總結:

【總結】Python 2.x中常見字符編碼和解碼方面的錯誤及其解決辦法

【整理】關於Python 3.x 中自動識別字符串編碼,並正確在cmd中輸出的各種情況的測試


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM