1. 程式人生 > >python新手必碰到的問題---encode與decode,中文亂碼[轉]

python新手必碰到的問題---encode與decode,中文亂碼[轉]

轉自:http://blog.csdn.net/a921800467b/article/details/8579510

為什麼會報錯“UnicodeEncodeError:'ascii' codec can't encode characters in position 0-1: ordinal notin range(128)”?本文就來研究一下這個問題。
字串在Python內部的表示是unicode編碼,因此,在做編碼轉換時,通常需要以unicode作為中間編碼,即先將其他編碼的字串解碼(decode)成unicode,再從unicode編碼(encode)成另一種編碼。

decode的作用是將其他編碼的字串轉換成unicode編碼,如str1.decode('gb2312'),表示將gb2312編碼的字串str1轉換成unicode編碼。

encode的作用是將unicode編碼轉換成其他編碼的字串,如str2.encode('gb2312'),表示將unicode編碼的字串str2轉換成gb2312編碼。

因此,轉碼的時候一定要先搞明白,字串str是什麼編碼,然後decode成unicode,然後再encode成其他編碼

程式碼中字串的預設編碼與程式碼檔案本身的編碼一致。

如:s='中文'

如果是在utf8的檔案中,該字串就是utf8編碼,如果是在gb2312的檔案中,則其編碼為gb2312。這種情況下,要進行編碼轉換,都需要先用decode方法將其轉換成unicode編碼,再使用encode方法將其轉換成其他編碼。通常,在沒有指定特定的編碼方式時,都是使用的系統預設編碼建立的程式碼檔案。

如果字串是這樣定義:s=u'中文'

則該字串的編碼就被指定為unicode了,即python的內部編碼,而與程式碼檔案本身的編碼無關。因此,對於這種情況做編碼轉換,只需要直接使用encode方法將其轉換成指定編碼即可。

如果一個字串已經是unicode了,再進行解碼則將出錯,因此通常要對其編碼方式是否為unicode進行判斷:

isinstance(s,unicode)#用來判斷是否為unicode

用非unicode編碼形式的str來encode會報錯

如何獲得系統的預設編碼?

#!/usr/bin/env python
#coding=utf-8
import sys
printsys.getdefaultencoding()

該段程式在英文WindowsXP上輸出為:ascii

該段程式在英文Windows7上輸出為:mbcs

在某些IDE中,字串的輸出總是出現亂碼,甚至錯誤,其實是由於IDE的結果輸出控制檯自身不能顯示字串的編碼,而不是程式本身的問題。

如在UliPad中執行如下程式碼:

s=u"中文"
print s

會提示:UnicodeEncodeError:'ascii' codec can't encode characters in position 0-1: ordinal notinrange(128)。這是因為UliPad在英文WindowsXP上的控制檯資訊輸出視窗是按照ascii編碼輸出的(英文系統的預設編碼是ascii),而上面程式碼中的字串是Unicode編碼的,所以輸出時產生了錯誤。

將最後一句改為:prints.encode('gb2312')

則能正確輸出“中文”兩個字。

若最後一句改為:prints.encode('utf8')

則輸出:\xe4\xb8\xad\xe6\x96\x87,這是控制檯資訊輸出視窗按照ascii編碼輸出utf8編碼的字串的結果。

unicode(str,'gb2312')與str.decode('gb2312')是一樣的,都是將gb2312編碼的str轉為unicode編碼

使用str.__class__可以檢視str的編碼形式


>>>>>
groups.google.com/group/python-cn/browse_thread/thread/be4e4e0d4c3272dd
-----
python是個容易出現編碼問題的語言。所以,我按照我的理解寫下下面這些文字。
=首先,要了解幾個概念。=
*位元組:計算機資料的表示。8位二進位制。可以表示無符號整數:0-255。下文,用“位元組流”表示“位元組”組成的串。
*字元:英文字元“abc”,或者中文字元“你我他”。字元本身不知道如何在計算機中儲存。下文中,會避免使用“字串”這個詞,而用“文字”來表
示“字元”組成的串。
*編碼(動詞):按照某種規則(這個規則稱為:編碼(名詞))將“文字”轉換為“位元組流”。(在python中:unicode變成str)
*解碼(動詞):將“位元組流”按照某種規則轉換成“文字”。(在python中:str變成unicode)
**實際上,任何東西在計算機中表示,都需要編碼。例如,視訊要編碼然後儲存在檔案中,播放的時候需要解碼才能觀看。
unicode:unicode定義了,一個“字元”和一個“數字”的對應,但是並沒有規定這個“數字”在計算機中怎麼儲存。(就像在C中,一個整數既
可以是int,也可以是short。unicode沒有規定用int還是用short來表示一個“字元”)
utf8:unicode實現。它使用unicode定義的“字元”“數字”對映,進而規定了,如何在計算機中儲存這個數字。其它的utf16等都是
unicode實現。
gbk:類似utf8這樣的“編碼”。但是它沒有使用unicode定義的“字元”“數字”對映,而是使用了另一套的對映方法。而且,它還定義瞭如何在
計算機中儲存。

=python中的encode,decode方法=
首先,要知道encode是 unicode轉換成str。decode是str轉換成unicode。
下文中,u代表unicode型別的變數,s代表str型別的變數。
u.encode('...')基本上總是能成功的,只要你填寫了正確的編碼。就像任何檔案都可以壓縮成zip檔案。
s.decode('...')經常是會出錯的,因為str是什麼“編碼”取決於上下文,當你解碼的時候需要確保s是用什麼編碼的。就像,開啟zip文
件的時候,你要確保它確實是zip檔案,而不僅僅是偽造了副檔名的zip檔案。
u.decode(),s.encode()不建議使用,s.encode相當於s.decode().encode()首先用預設編碼(一般是
ascii)轉換成unicode在進行encode。

=關於#coding=utf8=
當你在py檔案的第一行中,寫了這句話,並確實按照這個編碼儲存了文字的話,那麼這句話有以下幾個功能。
1.使得詞法分析器能正常運作,對於註釋中的中文不報錯了。
2.對於u"中文"這樣literal string能知道兩個引號中的內容是utf8編碼的,然後能正確轉換成unicode
3."中文"對於這樣的literalstring你會知道,這中間的內容是utf8編碼,然後就可以正確轉換成其它編碼或unicode了。

沒有寫完,先碼那麼多字,以後再來補充,這裡不是wiki,太麻煩了。

>>>>>
>>>>>
=Python編碼和Windows控制檯=
我發現,很多初學者出錯的地方都在print語句,這牽涉到控制檯的輸出。我不瞭解linux,所以只說控制檯的。
首先,Windows的控制檯確實是unicode(utf16_le編碼)的,或者更準確的說使用字元為單位輸出文字的。
但是,程式的執行是可以被重定向到檔案的,而檔案的單位是“位元組”。
所以,對於C執行時的函式printf之類的,輸出必須有一個編碼,把文字轉換成位元組。可能是為了相容95,98,
沒有使用unicode的編碼,而是mbcs(不是gbk之類的)。
windows的mbcs,也就是ansi,它會在不同語言的windows中使用不同的編碼,在中文的windows中就是gb系列的編碼。
這造成了同一個文字,在不同語言的windows中是不相容的。
現在我們知道了,如果你要在windows的控制檯中輸出文字,它的編碼一定要是“mbcs”。
對於python的unicode變數,使用print輸出的話,會使用sys.getfilesystemencoding()返回的編碼,把它變成str。
如果是一個utf8編碼str變數,那麼就需要 prints.decode('utf8').encode('mbcs')
最後,對於str變數,file檔案讀取的內容,urllib得到的網路上的內容,都是以“位元組”形式的。
它們如果確實是一段“文字”,比如你想print出來看看。那麼你必須知道它們的編碼。然後decode成unicode。
如何知道它們的編碼:
1.事先約定。(比如這個文字檔案就是你自己用utf8編碼儲存的)
2.協議。(python檔案第一行的#coding=utf8,html中的<meta>等)
2.猜。

>>>>>

> 這個非常好,但還不是很明白
> 將“文字”轉換為“位元組流”。(在python中:unicode變成str)

"最後,對於str變數,file檔案讀取的內容,urllib得到的網路上的內容,都是以“位元組”形式的。"
雖然檔案或者網頁是文字的,但是在儲存或者傳輸時已經被編碼成bytes了,所以用"rb"開啟的file和從socket讀取的流是基於位元組的.
"它們如果確實是一段“文字”,比如你想print出來看看。那麼你必須知道它們的編碼。然後decode成unicode。"
這裡的加引號的"文字",其實還是位元組流(bytes),而不是真正的文字(unicode),只是說明我們知道他是可以解碼成文字的.
在解碼的時候,如果是基於約定的,那就可以直接從指定地方讀取如BOM或者python檔案的指定coding或者網頁的meta,就可以正確解碼,
但是現在很多檔案/網頁雖然指定了編碼,但是檔案格式實際卻使用了其他的編碼(比如py檔案指定了coding=utf8,但是你還是可以儲存成ansi--記事本的預設編碼),這種情況下真實的編碼就需要去猜了
解碼了的文字只存在執行環境中,如果你需要列印/儲存/輸出給資料庫/網路傳遞,就又需要一次編碼過程,這個編碼與上面的編碼沒有關係,只是依賴於你的選擇,但是這個編碼也不是可以隨便選擇的,因為編碼後的bytes如果又需要傳遞給其他人/環境,那麼如果你的編碼也不遵循約定,又給下一個人/環境造成了困擾,於是遞迴之~~~~
>>>>>

> 主要有一條非常容易誤解:

>一般人會認為Unicode(廣義)統一了編碼,其實不然。Unicode不是唯一的編碼,而一大堆編碼的統稱。但是Windows下Unicode
> (狹義)一般特指UCS2,也就是UTF-16/LE

unicode作為字符集(ucs)是唯一的,編碼方案(utf)才是有很多種

>>>>>
將字元與位元組的概念區分開來是很重要的。Java一直就是這樣,Python也開始這麼做了,Ruby貌似還在混亂當中。
>>>>>
>>>>>
我也說兩句。我對編碼的研究相對比較深一些。因為工作中也經常遇到亂碼,於是在05年,對編碼專門做過研究,並在公司刊物上發過文章,最後形成了一個教材,每年在公司給新員工都講一遍。於是專案中遇到亂碼的問題就能很快的定位並解決了。
理論上,從一個字元到具體的編碼,會經過以下幾個概念。
字符集(Abstract character repertoire)
編碼字符集(Coded character set)
字元編碼方式(Character encoding form)
字元編碼方案(Character encoding scheme )
字符集:就算一堆抽象的字元,如所有中文。字符集的定義是抽象的,與計算機無關。
編碼字符集:是一個從整數集子集到字符集抽象元素的對映。即給抽象的字元編上數字。如gb2312中的定義的字元,每個字元都有個整數和它對應。一個整數只對應著一個字元。反過來,則不一定是。這裡所說的對映關係,是數學意義上的對映關係。編碼字符集也是與計算機無關的。unicode字符集也在這一層。
字元編碼方式:這個開始與計算機有關了。編碼字符集的編碼點在計算機裡的具體表現形式。通俗的說,意思就是怎麼樣才能將字元所對應的整數的放進計算機記憶體,或檔案、或網路中。於是,不同人有不同的實現方式,所謂的萬碼奔騰,就是指這個。gb2312,utf-8,utf-16,utf-32等都在這一層。
字元編碼方案:這個更加與計算機密切相關。具體是與作業系統密切相關。主要是解決大小位元組序的問題。對於UTF-16和UTF-32
編碼,Unicode都支援big-endian 和 little-endian兩種編碼方案。
一般來說,我們所說的編碼,都在第三層完成。具體到一個軟體系統中,則很複雜。
瀏覽器-apache-tomcat(包括tomcat內部的jsp編碼、編譯,檔案讀取)-資料庫之間,只要存在資料互動,就有可能發生編碼不一致,如果在讀取資料時,沒有正確的decode和encode,出現亂碼就是家常便飯了。

相關推薦

pythonpython新手碰到的問題---encodedecode中文亂碼[]

為什麼會報錯“UnicodeEncodeError:'ascii' codec can't encode characters in position 0-1: ordinal notin range(128)”?本文就來研究一下這個問題。字串在Python內部的表示是unicode編碼,因此,在做編碼轉換

python新手碰到的問題---encodedecode中文亂碼[]

轉自:http://blog.csdn.net/a921800467b/article/details/8579510 為什麼會報錯“UnicodeEncodeError:'ascii' codec can't encode characters in position 0-1: ordinal notin

python基礎-encodedecode中文亂碼

來源:http://blog.csdn.net/a921800467b/article/details/8579510 為什麼會報錯“UnicodeEncodeError:'ascii' codec can't encode characters in position 0-1: ordi

Python中的encodedecode詳解字串位元組物件之間的轉換

1.相關異常我們在處理交換的資料時經常遇到這樣的異常:TypeError: can't use a string pattern on a bytes-like objectTypeError: a bytes-like object is required, not 'st

Python3字串的encodedecode研究——解決亂碼的問題

2017/12/2 我開始寫部落格了,先從python學起,一步一個腳印,加油穆鴻繼。 為什麼Python使用過程中會出現各式各樣的亂碼問題,明明是中文字元卻顯示成“/xe4/xb8/xad/xe6/x96/x87”的形式?為什麼會報錯“UnicodeEncodeErr

python發郵件總結及例項說明中文亂碼已解決(在最後一個模組)

python發郵件需要掌握兩個模組的用法,smtplib和email,這倆模組是python自帶的,只需import即可使用。smtplib模組主要負責傳送郵件,email模組主要負責構造郵件。 smtplib模組主要負責傳送郵件:是一個傳送郵件的動作,連線郵箱伺服器,登入郵箱,傳送郵件(有發件

Python 關於 encodedecode 中文亂碼問題

字串在Python內部的表示是unicode編碼,因此,在做編碼轉換時,通常需要以unicode作為中間編碼,即先將其他編碼的字串解碼(decode)成unicode,再從unicode編碼(encode)成另一種編碼。 decode的作用是將其他編碼的字串轉換成unicode編碼,如str1.decode

Python字串的編碼解碼(encodedecode)

首先要搞清楚,字串在Python內部的表示是unicode編碼,因此,在做編碼轉換時,通常需要以unicode作為中間編碼,即先將其他編碼的字串解碼(decode)成unicode,再從unicode編碼(encode)成另一種編碼。 decode的作用是將其他編碼的字串轉換成unicode編碼,如str1

Python字串的encodedecode研究心得——解決亂碼問題

為什麼Python使用過程中會出現各式各樣的亂碼問題,明明是中文字元卻顯示成“/xe4/xb8/xad/xe6/x96/x87”的形式?為什麼會報錯“UnicodeEncodeError: 'ascii' codec can't encode characters in po

優酷url的encodedecode

以前在優酷上看到一個關於微軟的視訊,感覺不錯。但是是以前無意中看到的,現在唯一能找到的痕跡是一個殘缺的url-1,https%253A%252F%252Fv.youku.com%252Fv_show%252Fid_XMzc4NDA%253D.html,當然把這個url貼上到browser的位址列中是無效的

尚學堂 python新手入門到精通400集全棧工程師!

全棧工程師是指掌握多種技能,並能利用多種技能獨立完成產品的人, 也叫全端工程師(同時具備前端和後臺能力),英文Full Stack engineer。 現代專案的開發,需要掌握多種技術。網際網路專案,需要用到後端開發、前端開發、介面設計、產品設計、資料庫、各種

GO 語言URL encodedecode方法

GO 筆記 - GO 語言http請求編碼 在go中將url.Values 型別進行url encode使用函式url.Values.Encode() url decode 使用 url.ParseQuery(string) pac

encodedecode

import torch from torch import nn import numpy as np import matplotlib.pyplot as plt import torch.utils.data as Data import torchvision from mpl_toolkit

python物件資料型別IteratorSequece Mapping and Set的區別

前言: 迭代器都是能夠可迭代和具有__iter__屬性的 但是能夠可迭代和具有__iter__屬性的不一定就是迭代器(iterator),它比迭代器要高一個等級。 iterator(迭代器) 必須有兩種方法: next:Return the next item from

python3大作戰之encodedecode講解

大家好,很久沒更新了,也是年底了最近比較忙,同時也在研究python的其他內容,畢竟是python小白,自學道路艱難。 好了今天和大家一起探討下python3編碼過程中對的一些轉碼事宜。 python3中對文字和二進位制做了比較清晰的區分。python3預設編碼為unico

python中字串的encodedecode

為什麼Python使用過程中會出現各式各樣的亂碼問題,明明是中文字元卻顯示成“/xe4/xb8/xad/xe6/x96/x87”的形式?為什麼會報錯“UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1:

eclipse匯入外部專案後中文顯示亂碼問題解決SQLyogMySql資料庫中文亂碼問題其他亂碼問題

要解決中文亂碼問題,就是要保持不同的位置的編碼方式一致,目前我們通常使用UTF-8編碼,將不同的位置改為相同的編碼即可。 首先是在eclipse工作環境中,對不同的編碼進行更改: 右擊專案名稱,選擇properties,將其中涉及編碼的地方都改為UTF-8即可。  

jsonlistmap互 ,Json語法

Json 定義Json語法Json使用JSON 解析器Json與常見的型別之間的轉換Json-jar包下載連結定義        JSON(JavaScript Object Notation, JS 物件標記) 是一種輕量級的資料交換格式。       它基於 ECMASc

Python 讀取Oracle數據中文亂碼問題

con nec gbk utf 字段 decode tin 編碼 中文亂碼問題 DB:Oracle11g 字符集:AMERICAN_AMERICA.WE8ISO8859P1 Python讀數據時: conn=cx_Oracle.connect(g_conn_str,e

web項目存數據到數據庫中文亂碼解決過程

問題 async sql安裝 -s pat character value 127.0.0.1 supported 排查原因: 打斷點,查看到底是在執行存數據庫操作之前就已經亂碼了,還是存數據庫操作後亂碼的。 前者解決方案: 在web.xml裏面加上: <