Python字符編碼

字符編碼

計算機只認識數字,咱們平時在使用計算機時,用的都是人類能讀懂的字符(用高級語言編程的結果也無非是在文件內寫了一堆字符),如何能讓計算機讀懂人類的字符?必須通過一個過程: 字符--------(翻譯過程)------->數字 這個過程實際就是一個字符如何對應一個特定數字的標準,這個標準稱之爲字符編碼node

1、存取文件的原理(nodepad++,pycharm,word)

  • a、打開編輯器就打開了啓動了一個進程,是在內存中的,因此,用編輯器編寫的內容也都是存放與內存中的,斷電後數據丟失
  • b、要想永久保存,須要點擊保存按鈕:編輯器把內存的數據刷到了硬盤上。
  • c、在咱們編寫一個py文件(沒有執行),跟編寫其餘文件沒有任何區別,都只是在編寫一堆字符而已。

2、編碼發展

  • 階段1:現代計算機起源於美國,最先誕生也是基於英文考慮的ASCII,ASCII:用1個字節Bytes(8位二進制)表明一個字符
  • 階段2:爲了知足中文和英文,中國人定製了GBK, GBK:2Bytes表明一箇中文字符,1Bytes表示一個英文字符
  • 階段3:各國有各國的標準,出現衝突,unicode出現了,可以兼容萬國字符。 unicode(定長):經常使用2個字節(16位二進制)表明一個字符,生僻字須要用4個字節
  • 階段4:對於通篇都是英文的文原本說,unicode的式無疑是多了一倍的存儲空間(二進制最終都是以電或者磁的方式存儲到存儲介質中的)因而產生了UTF-8(可變長,全稱Unicode Transformation Format)UTF-8:對英文字符只用1Bytes表示,對中文字符用3Bytes,對其餘生僻字用更多的Bytes去存。

3、亂碼來源

  • 亂碼1:存文件時就已經亂碼
  • 存文件時,因爲文件內有各個國家的文字,咱們單以shiftjis去存, 本質上其餘國家的文字在shiftjis中沒有找到對應關係,不能存而硬存,確定是亂存了,即存文件階段就已經發生亂碼,而當咱們用shiftjis打開文件時,日文能夠正常顯示,而中文則亂碼了。
  • 亂碼2:存文件時不亂碼而讀文件時亂碼【按照什麼標準編碼的,就要按照什麼標準解碼】
  • 存文件時用utf-8編碼,保證兼容萬國,不會亂碼,而讀文件時選擇了錯誤的解碼方式,好比gbk,則在讀階段發生亂碼,讀階段發生亂碼是能夠解決的,選對正確的解碼方式就ok了,

4、特別說明

  • 指定頭信息#-*-coding:utf-8-*- python解釋器編碼就是頭信息編碼, 沒有指定頭信息,那就使用默認的python2中默認使用ascii,python3中默認使用utf-8。
  • 在python2中有兩種字符串類型str(編碼成文件頭指定的編碼格式)和unicode 在python3 中也有兩種字符串類型str(直接編碼成unicode)和bytes python2中的str類型就是python3的bytes類型
  • 特別說明print時,open時,沒指定編碼格式就使用終端的編碼格式。
  • sys.stdout.encoding,默認就是locale的編碼,print會用sys.stdout.encoding去encode()成字節流,交給terminal顯示。因此locale須要與terminal一致,才能正確print打印出中文。
  • 瀏覽網頁的時候,服務器會把動態生成的Unicode內容轉換爲UTF-8再傳輸到瀏覽器
  • 若是服務端encode的編碼格式是utf-8, 客戶端內存中收到的也是utf-8編碼的結果。
  • *****內存中統一採用unicode,浪費空間來換取能夠轉換成任意編碼(不亂碼),硬盤能夠採用各類編碼,如utf-8,保證存放於硬盤或者基於網絡傳輸的數據量很小,提升傳輸效率與穩定性。*****
  • ***在存入磁盤時,須要將unicode轉成一種更爲精準的格式,utf-8****
  • ***在讀入內存時,須要將utf-8轉成unicode****

5、python解釋器執行py文件的3個階段

  • 階段1:啓動python解釋器至關於啓動了一個文本編輯器
  • 階段2:從硬盤讀取test.py文件內容到內存。【此時,python解釋器會讀取test.py的頭信息#-*-coding:utf-8-*-,來決定以什麼編碼格式讀入到內存,能夠用sys.getdefaultencoding()查看,若是沒有指定頭信息#-*-coding:utf-8-*-,那就使用python解釋器默認的編碼,python2中默認使用ascii,python3中默認使用utf-8。】
  • 階段3:解釋執行階段。【在該階段,纔會識別python的語法,執行文件內代碼,當執行到name="tom"時,會開闢內存空間存放字符串"tom"。】
  • python解釋器比文本編輯器多了階段3

細說階段3

  • 在程序執行以前,內存中都是unicode
  • 程序在執行過程當中,會申請內存(與程序代碼所存在的內存是倆個空間)用來存放python的數據類型的值,好比x="tom",會被python解釋器識別爲字符串,會申請內存空間來存放字符串類型的值,至於該字符串類型的值被識別成何種編碼存放,這就與python解釋器有關了,而python2與python3的字符串類型又有所不一樣。  
  • 在python2中有兩種字符串類型str(編碼成文件頭指定的編碼格式)和unicode
  • 在python3中也有兩種字符串類型str(直接是unicode)和bytes (也就是python2中的str)
  • 字節字符串和字符字符串
  • (內存)unicode----->encode-------->utf-8(硬盤)
  • (硬盤)utf-8----->decode-------->unicode(內存)

6、總結

  • 字符按照什麼標準而編碼的,就要按照什麼標準解碼
  • 在內存中寫的全部字符,一視同仁,都是unicode編碼,好比咱們打開編輯器,輸入一個「你」,咱們並不能說「你」就是一個漢字,此時它僅僅只是一個符號,該符號可能不少國家都在使用,根據咱們使用的輸入法不一樣這個字的樣式可能也不太同樣。只有在咱們往硬盤保存或者基於網絡傳輸時,才能肯定」你「究竟是一個漢字,仍是一個日本字,這就是unicode轉換成其餘編碼格式的過程了
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
#將bytes轉換爲str
name_b = b 'tom'
name_s1 = name_b.decode( 'utf-8' )
name_s2 = str (name_b,encoding = 'utf-8' )
print (name_b, type (name_b)) #b'tom' <class 'bytes'>
print (name_s1, type (name_s1)) #tom <class 'str'>
print (name_s2, type (name_s2)) #tom <class 'str'>
 
#將str轉換爲bytes
gender = 'male'
gender_b1 = gender.encode( 'utf-8' )
gender_b2 = bytes(gender,encoding = 'utf-8' )
print (gender, type (gender)) #male <class 'str'>
print (gender_b1, type (gender_b1)) #b'male' <class 'bytes'>
print (gender_b2, type (gender_b2)) #b'male' <class 'bytes'>