Python中的編碼問題


視頻彙總首頁:http://edu.51cto.com/lecturer/index/user_id-4626073.htmlhtml

對於Python的初學者來講,編碼問題至關使人頭疼。本文就根據我在學習過程當中遇到的問題簡單談一下Python中的編碼。首先簡單介紹一下幾種常見的編碼。python

1、幾種常見的字符編碼windows

ASCII碼數組

ASCII碼是基於拉丁字碼的一套電腦編碼系統。它對英語字符與二進制位之間的關係作了統一的規定,使用指定的7位或8爲二進制數組合來表示128或256種可能的字符。標準ASCII碼也叫基礎ASCII碼,使用7位二進制來表示全部的大寫和小寫字母,數字0到九、標點符號,以及在美式英語中使用的特殊控制字符。微信

英語中英文字母用128個符號編碼就夠了,可是用來表示其餘語言,128個符號顯然是不夠的。好比,在法語中,字母上方有注音符號,它就沒法用ASCII碼錶示。至於亞洲國家的文字,使用的符號就更多了,漢字就多達10萬左右。ide

Unicode學習

Unicode統一碼、萬國碼、單一碼)是一種在計算機上使用的字符編碼。Unicode 是爲了解決傳統的字符編碼方案的侷限而產生的,它爲每種語言中的每一個字符設定了統一而且惟一的二進制編碼,以知足跨語言、跨平臺進行文本轉換、處理的要求。字體

UTF-8網站

UTF-8(8位元Universal Character Set/Unicode Transformation Format)是一種針對Unicode的可變長度字符編碼。UTF-8最大的一個特色,是它是一種變長的編碼方式。它能夠用來表示Unicode標準中的任何字符,且其編碼中的第一個字節與ASCII相容。UTF-8是在互聯網上使用最廣的一種Unicode的實現方式。編碼

2、Python中的字符串類型

Python中的字符串有兩種類型:str類型和unicode類型。以字符串「中文」賦值給變量爲例:

wKioL1ZzdrKDdTIfAAAIpaYu4Ao256.png或者wKioL1ZzdsDyOpeVAAAJcOrpI8c627.png

在Python中,爲了統一不一樣編碼的字符串的表示,同時簡化字符串的處理,其內部提供了一種統一化的文本類型unicode,即第二種形式的字符串。unicode類型的字符串只處理文本,並把文本以unicode形式在內部存儲。unicode類型的做用只用於代碼內部字符串的處理,而不關心外部文本的具體格式,能夠看做是文本的抽象表示。前者定義了一個字符串,後者定義了一個unicode編碼的字符串。

可是實際上外界文本的不一樣編碼格式衆多。好比向一個網站提交數據,其有可能要求utf-8的編碼或者gbk的編碼,不一樣的編碼類型的內容是不一樣的, 這就須要將程序內部字符串轉換成能夠與外界交互的編碼(如:utf-8,ascii,gdb等)。Python默認使用str類型來操做。嚴格來說,str並不必定是文本,它也有多是二進制的內容,它提供的實際上是字節的組合(unicode類型提供的是unicode字符集的組合),只是若是str中恰好是某種形式編碼的文本,它即可以當作文本處理(print等)。

3、python中常遇到的編碼問題

如下問題只有在Python2.x版本中出現,由於3.X版本中python環境就只有unicode類型的字符串了,即全部程序中處理的都會自動轉換成unicode字符串。

1. 代碼文件編碼聲明

編寫Python腳本時,教程都會讓咱們把「# -*- coding: utf-8 -*-」加在代碼文件的第一行。這句話是告訴python這個文件裏的文本用utf-8編碼。Python默認將代碼文件內容當作ASCII編碼處理,所以當文件中存在中文時就會拋出異常。加上這句編碼聲明後,Python就會依照utf-8的編碼形式解讀其中的字符,然會轉換成unicode編碼內部處理使用。注意這句編碼聲明必定要放在第一行或者第二行才生效,我以前就將它放在了其餘位置,結果將源代碼文件從windows移動到Linux後,出現了編碼問題,文件中的中文註釋全成了亂碼。由於Windows中默認編碼爲gbk,Linux默認編碼爲utf-8。

或者也可使用下面的語句來設置編碼方式:

wKioL1ZzduqwVkQpAAANI8ItFRU716.png

2. 編碼轉換

編寫python過程當中常常遇到報錯「UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 0-1: ordinal not in range(128)」,爲何會出這樣的報錯呢?

第二節提到,字符串在Python內部使用unicode編碼,所以,在作編碼轉換時,一般須要以unicode做爲中間編碼,即先將其餘編碼的字符串解碼(decode)成unicode,再從unicode編碼(encode)成另外一種編碼。

decode的做用是將普通字符串按照參數中的編碼格式進行解析,而後生成對應的unicode對象。如str1.decode(‘gb2312′),表示將字符串str1按照gb2312編碼解析爲unicode對象。

encode的做用正好相反,是將一個unicode對象轉換爲參數中指定的編碼格式的普通字符。如str2.encode(‘gb2312′),表示將unicode對象str2轉換成gb2312編碼的字符串。

所以,轉碼的時候必定要先搞明白,字符串str是什麼編碼,而後decode成unicode,而後再encode成其餘編碼。

代碼中字符串的默認編碼與代碼文件自己的編碼一致。也就是說,在utf8的文件中,字符串就是utf8編碼,若是是在gb2312的文件中,則其編碼爲gb2312。一般,在沒有指定特定的編碼方式時,都是使用的系統默認編碼建立的代碼文件。

若是字符串是這樣定義:s=u’中文’

則該字符串就被定義爲unicode對象了,即python的內部編碼,而與代碼文件自己的編碼無關。所以,對於這種狀況作編碼轉換,只須要直接使用encode方法將其轉換成指定編碼便可。

若是一個字符串已是unicode了,再進行解碼則將出錯,所以一般要對其編碼方式是否爲unicode進行判斷:

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


一樣,用非unicode編碼形式的str來encode會報錯 。

所以,程序會提示:UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 0-1: ordinal not in range(128),是由於Python調用了ASCII編碼解碼程序去處理unicode對象,致使拋出異常(ordinal not in range(128))。解決辦法則是用上一小節提到的第二種設置編碼的方式來修改默認的編碼模式便可。

3. 輸出打印

咱們在windows控制檯下打印中文時,常常出現屏幕上打印出的字和咱們想要的結果不一致的狀況。這是因爲python編碼與控制檯編碼不一致形成的。Windows下控制檯中的編碼默認使用的是gbk,而在代碼中使用的是utf-8,python按照utf-8編碼打印到gbk編碼的控制檯下天然就不能打印出正確的漢字。

解決辦法一個是將源代碼的編碼方式改爲gbk,也就是將源代碼文件的第一行改爲:

# -*- coding: gbk -*-


另外一種方式是保持源代碼文件的utf-8編碼方式不變,而是在聲明帶中文的變量前u,如:s1=u’中文’,這樣就能夠正確打印中文了。

這裏的u表示將後面跟的字符串以unicode格式存儲。python會根據代碼第一行聲明的utf-8編碼識別代碼中的漢字,而後轉換成unicode對象以unicode格式存在於內存中,而若是不加u,代表這僅僅是一個使用某種編碼的字符串,編碼格式取決於python對源碼文件編碼的識別,這裏就是utf-8。Python在向控制檯輸出unicode對象的時候會自動根據輸出環境的編碼進行轉換,但若是輸出的不是unicode對象而是普通字符串,則會直接按照字符串的編碼輸出字符串,從而出現上面的現象。

4. 文件的讀取

在對文件內容進行讀取時也常常出現編碼問題。這裏咱們首先來了解一下文件編碼。

文件編碼即文件的編碼方式。嚴格意義上來講,文件沒有編碼之說,都是按二進制格式保存在硬盤中的,只是在寫入讀取時需使用對應的編碼進行處理,以便操做系統配合相關軟件/字體,繪製到屏幕中給人看。因此關鍵問題是得知道文件內容是使用什麼方式編碼成二進制碼存入到磁盤中的。

Linux中Vim下可以使用命令set fileencoding來查看文件編碼。

Windows中txt文件點擊「文件」–>「另存爲」,查看「編碼」顯示的編碼方式(ANSI:非Unicode編碼方式,對於英文系統即ASCII編碼,中文系統則爲GB2312或Big5編碼;其他三種爲「Unicode」(對應UTF-16 LE)、「Unicode big endian」(對應UTF-16 BE)和「UTF-8」)。

知道文件編碼方式後,只須要在讀取文件時使用相同的編碼方式對內容進行解碼就能得到正確的文件內容。

wKiom1ZzdybBqEBgAAAwCsl18wc887.png

但不少狀況下咱們無從知曉文件的編碼方式,此時可使用python提供的Chardet包。

Character encoding auto-detection(自動字符探測器),Python中一個強力的編碼檢測包。使用方式很是簡單。

wKioL1Zzd0-Bog3xAAAjrJ6VaUs414.png

知道字符串的編碼後就能夠利用decode和encode實現編碼的轉換獲得正確的文件內容了。

所以,Python中的編碼問題解決方式總結起來就是:保證字符串的編碼及解碼方式一致,瞭解了文中提到相關知識相信能解決Python中大部分的編碼問題了。

wKiom1Zzd1mzWkd1AAC7xM3r2nY215.jpg

相關文章
相關標籤/搜索