python 字符编码
1.Python Unicode字符串
字符串還有一個編碼問題。
由于計算機只能處理數字,若是要處理文本,就必須先把文本轉換為數字才能處理。最先的計算機在設計時采用8個比特(bit)做為一個字節(byte),因此,一個字節能表示的最大的整數就是255(二進制11111111=十進制255),0 - 255被用來表示大小寫英文字母、數字和一些符號,這個編碼表被稱為ASCII編碼,好比大寫字母 A 的編碼是65,小寫字母 z 的編碼是122。
若是要表示中文,顯然一個字節是不夠的,至少須要兩個字節,并且還不能和ASCII編碼沖突,因此,中國制定了GB2312編碼,用來把中文編進去。
相似的,日文和韓文等其余語言也有這個問題。為了統一全部文字的編碼,Unicode應運而生。Unicode把全部語言都統一到一套編碼里,這樣就不會再有亂碼問題了。
Unicode一般用兩個字節表示一個字符,原有的英文編碼從單字節變成雙字節,只須要把高字節所有填為0就能夠。
由于Python的誕生比Unicode標準發布的時間還要早,因此最先的Python只支持ASCII編碼,普通的字符串'ABC'在Python內部都是ASCII編碼的。
Python在后來添加了對Unicode的支持,以Unicode表示的字符串用u'...'表示,好比:
print u'中文'
中文
注意: 不加 u ,中文就不能正常顯示。
Unicode字符串除了多了一個 u 以外,與普通字符串沒啥區別,轉義字符和多行表示法仍然有效:
轉義:
u'中文\n日文\n韓文'
多行:
u'''第一行
第二行'''
raw+多行:
ur'''Python的Unicode字符串支持"中文",
"日文",
"韓文"等多種語言'''
若是中文字符串在Python環境下遇到 UnicodeDecodeError,這是由于.py文件保存的格式有問題。能夠在第一行添加注釋
# -*- coding: utf-8 -*-
目的是告訴Python解釋器,用UTF-8編碼讀取源代碼。而后用Notepad++ 另存為... 并選擇UTF-8格式保存。
2.解析unicode編碼的字符串
使用python抓取頁面或者web端的json時候很容易抓到一些unicode編碼的字符串流。在python里邊對Unicode編碼的處理成了一件頭疼的事。?
對于string里邊不含"引號的處理比較簡單,使用eval注明引入str是unicode編碼:
str1 = eval("u"+"\""+str + "\"")str1.decode('utf8')對于包含引號的明文,須要先把引號轉化為 \",而后能夠進行eval函數處理。?web
str=str.replace("\\\"","\\\\\"") #先轉化字符串中的\" str=str.replace("\"","\\\"") #再轉化 "print eval("u"+"\""+str+"\"")對于json格式unicode的有個很奇怪的處理:
python 的json 庫在使用 json.loads()函數時候會默認把輸入中unicode編碼解析好,而不是保留原輸入。?函數
代碼:?編碼
str1="{\"html\":\"\u003c\u003e\"}" s=json.loads(str1) print s["html"] 輸出:<>輸出<>而不是 \u003c 這也引出了一個問題:python的json庫解析json不徹底保留原格式,使用時候要注意。?
若是想要json解析保持unicode編碼比較麻煩,需要將unicode碼的\改成\\,轉譯代碼以下:?
str="{\"html\":\"\u003c\"}" s=str.replace("\\u","\\\\u") s2=json.loads(s) print s2["html"] 輸出: \u003c3.str字符串和unicode字符串
字符編碼
咱們在編輯器中輸入的文字,對用戶來講是可讀的。可是機器只能讀懂01串,那怎么把咱們方便閱讀的符號轉換成機器能讀懂的01串呢?程序員
這就需要給出符號-二進制之間的映射關系,并且必須是一一映射:即給定一個符號,機器有并且有惟一的二進制對應。根據字符獲得二進制表示是編碼過程(encode);根據二進制表示獲得字符是解碼過程(decode)。web
ASCII字符集與字符編碼
剛開始的時候,給出了ASCII標準,用一個8bits字節來表示字符。并且這個字節實際上只用了7位,最高位是不用的,這樣總共能表示128個字符。意味著ASCII字符集只有128個。數據庫
隨著計算機的普及,愈來愈多的國家開始使用計算機。128個字符難以知足各個國家的語言需求,這促使包含更多字符的字符集誕生,而且須要采用新的編碼方案。網絡
Latin-1
充分利用8bits字節的高位,擴展到256個字符。編輯器
Unicode字符集與字符編碼
Unicode字符集包含了全部種語言的全部字符。一般用U+后接4位的16進制數字表示一個Unicode字符,好比U+FFFF。svg
UTF-8編碼
UTF-8是針對Unicode字符集的一種編碼方案。編碼
用變長字節來表示字符:有的字符用一個字節表示(好比ASCII中規定的字符),有的字符用2個字節表示。最大長度為4字節。spa
上面這張圖是從Wikipedia中截取的。Number of Bytes列表示字節數;Bits for code point列表示多少個bit位是真正有用的;First code point列表示該字節數能表示的第一個Unicode字符;Last code point列表示對應字節數能表示的最后一個Unicode字符;Byte i(i=1,2,3,4)列表示第i字節上的bit值。
以第二行為例,這一行的編碼需要兩個字節,其中真正有用的bit位只有11個,另5位是占位符,能表示從U+0080~U+07FF的Unicode字符。code
至于具體的編碼方式,咱們以歐元符號€為例。€在Unicode字符集中對應U+20AC:
- U+20AC位于U+0800~U+FFFF之間,因此須要三個字節來表示;
- 十六進制20AC能夠寫成二進制:0010?0000 1010 1100;
- 前4個bit放在第一字節的低4位:11100010;
- 中間6個bit放在第二字節的低6位:10000010;
- 后6個bit放在第三字節的低6位:10101100;
因而€的UTF-8編碼為:11100010 10000010 10101100。
Unicode字符集還有其余的編碼方式,這里就介紹到這里。
要記住:全部的編碼方式都是向后兼容ASCII的。ASCII字符對應什么二進制,那么在其余編碼方式中也對應一樣的二進制。
3.Python的字符串類型
Python包含兩種字符串類型:str(其實就是二進制)和unicode。當只會用到ASCII字符集時,一切相安無事。一旦出現其余字符集,問題也就接踵而來。因此下面咱們著重介紹非ASCII字符串。
- str類型
咱們平時寫的用引號括起來的字符串都是str類型的。
根據上面的打印結果,能夠知道str類型的x存的實際上是二進制序列,而非字符串。為何會出現這種狀況呢?咱們賦給x的明明是字符串。
其實很簡單,x通過了一次隱形的編碼過程encode()。應該采用的是系統默認編碼方案。
- unicode類型
若是在引號的前面加上字符u,那么咱們就獲得一個unicode字符串:
unicode對象保存的是字符串自己,而非二進制序列。好比程序中的unicode字符串中包含兩個U+54c8字符。
unicode編碼為str
可是有的時候,咱們須要二進制序列,好比將數據寫入文件、發送到網絡或者寫入數據庫中時。若是不進行任何處理,會出現錯誤:
<span style="color:#000000">>>> x = <span style="color:#219161"><span style="color:#219161">u'哈哈'</span></span> >>> x <span style="color:#219161"><span style="color:#219161">u'\u54c8\u54c8'</span></span> >>> f = open(<span style="color:#219161"><span style="color:#219161">'test.txt'</span></span>, <span style="color:#219161"><span style="color:#219161">'w'</span></span>); >>> f.write(x) Traceback (most recent call last):File <span style="color:#219161"><span style="color:#219161">"<stdin>"</span></span>, line <span style="color:#40a070"><span style="color:#40a070">1</span></span>, <span style="color:#954121"><span style="color:#954121">in</span></span> <module> UnicodeEncodeError: <span style="color:#219161"><span style="color:#219161">'ascii'</span></span> codec can<span style="color:#219161"><span style="color:#219161">'t encode characters in position 0-1: ordinal not in range(128)</span></span></span>這是由于在把字符串寫入文件時,會首先檢查字符串的類型,若是是str類型的字符串,那么一切OK;若是是unicode類型的字符串,那么會隱式地對其編碼,即x.encode()。而系統默認的編碼方案是ASCII(能夠經過sys.getdefaultencoding()查看),對非ASCII字符進行編碼的時候,確定會出現錯誤。
為了不錯誤,在寫入文件以前,應該用utf-8或者gbk編碼方案對unicode字符串編碼:
<span style="color:#000000">>>> x = <span style="color:#219161"><span style="color:#219161">u'哈哈'</span></span> >>> x <span style="color:#219161"><span style="color:#219161">u'\u54c8\u54c8'</span></span> >>> f = open(<span style="color:#219161"><span style="color:#219161">'test.txt'</span></span>, <span style="color:#219161"><span style="color:#219161">'w'</span></span>); >>> x = x.encode(<span style="color:#219161"><span style="color:#219161">'utf-8'</span></span>) <span style="color:#408080"><em><span style="color:#408080"><em>#unicode -> str</em></span></em></span> >>>x <span style="color:#219161"><span style="color:#219161">'\xe5\x93\x88\xe5\x93\x88'</span></span> >>> f.write(x)</span>str解碼為unicode
當從文本中讀取數據時,讀到的是str字符串,并且咱們已經知道,它保存的是二進制序列。若是其中包含非ASCII文本,咱們應該怎么恢復呢?這時候就要用到解碼decode()。
<span style="color:#000000">>>> f = open(<span style="color:#219161"><span style="color:#219161">'test.txt'</span></span>, <span style="color:#219161"><span style="color:#219161">'w'</span></span>); >>> x = f.read() >>> x <span style="color:#219161"><span style="color:#219161">'\xe5\x93\x88\xe5\x93\x88'</span></span> >>> x = x.decode(<span style="color:#219161"><span style="color:#219161">'utf-8'</span></span>) <span style="color:#408080"><em><span style="color:#408080"><em>#str -> unicode</em></span></em></span> >>> x <span style="color:#219161"><span style="color:#219161">u'\u54c8\u54c8'</span></span></span>必定要記得,用什么方式編碼的就必須用什么方式解碼。否則的話,從二進制到字符的對應過程會出現UnicodeDecodeError。
print語句
print語句的參數須要是str類型,并且在執行的時候會用系統的編碼方式對str進行隱式解碼。
兩個遺留問題
-
#-*-coding:utf-8 -*-
如今暫且認為若是腳本中包含中文,那么必須加上這個聲明。 -
setdefaultencoding()?這個方法貌似如今不能夠用了。我以為這個設置與encode()、decode()在不指明參數的狀況下的默認參數有關。
總結
以上是生活随笔為你收集整理的python 字符编码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VS Code运行Python程序
- 下一篇: tail | grep引起的内存升高【对