Python2 和 Python3 編碼問題

基本存儲單元

  • 位(bit, b):二進制數中的一個數位,能夠是0或者1,是計算機中數據的最小單位。
  • 字節(Byte,B):計算機中數據的基本單位,每8位組成一個字節。
  • 1B = 8b
  • 各類信息在計算機中存儲、處理,至少須要一個字節的空間。

 

字節與字符

  • 計算機存儲的一切數據都是由一串 0 和 1 組成的字節序列構成。
  • 字符就是一個符號,好比一個漢字、一個英文字母、一個標點均可以稱爲一個字符。

 

編碼與解碼

  • 咱們用編輯器打開的文本,看到的一個個字符,最終保存在磁盤上的時候都是以二進制字節序列形式存起來的。那麼從字符到字節的轉換過程就叫作編碼(encode),反過來叫作解碼(decode),二者是一個可逆的過程。編碼是爲了存儲傳輸,解碼是爲了方便顯示閱讀。

 

編碼規則

  • 編碼是人們定義的一種規則,使字符能夠根據該規則,轉換爲對應的字節,方便存儲和傳輸,也可使字節轉化成對應的字符用於顯示、閱讀。
  • 例如,按照 ASCII 編碼進行轉換,字符 A 對應的字節爲 0100 0001,佔用 1 個字節的大小,一個字節也就是8位,能夠表示 0 - 255,對於英文來說 255 個字符已經足夠顯示全部的英文字符了,因此 ASCII(每一個 字符佔用一個字節) 編碼是美國的標準編碼
  • 可是 ASCII 處理中文明顯是不夠的,中文不止 255 個漢字,因此中國製定了 GB2312 編碼,用兩個字節表示一個漢字。GB2312 還把 ASCII 包含進去了,同理,日文,韓文等等上百個國家爲了解決這個問題就都發展了一套字節的編碼,標準就愈來愈多,若是出現多種語言混合顯示就必定會出現亂碼
  • 因而 unicode 出現了,將全部語言統一到一套編碼裏,每個 unicode 字符佔用兩個字節的大小空間
  • 亂碼問題解決了,可是若是內容全是英文,unicode 編碼比 ASCII 須要多一倍的存儲空間,同時若是進行網絡傳輸也須要傳輸多一倍的數據
  • 因此出現了可變長的編碼 "utf-8",把英文變長一個字節,漢字 3 個字節。特別生僻的變成4-6字節,若是傳輸大量的英文,utf-8做用就很明顯了。

 

encode() 和 decode()

  • decode 英文意思爲 解碼,encode 英文意思爲 編碼
  • decode 的做用是將其餘編碼轉換成 unicode編碼,例如 str1.decode('gbk'),表示將 gbk 編碼的字符串 str1 轉換成 unicode 編碼
  • encode 的做用是將 unicode 編碼的字符串,轉換成其餘編碼的字符串,例如str2.encode('gbk'),表示將 unicode 編碼的字符串st2,轉換爲 gbk 編碼
  • 在 Python2 中,windows 簡體中文平臺下,字符串表示是 GBK 編碼,在 Linux 平臺下表示爲 UTF8編碼,能夠在字符串定義時,修改字符編碼格式,定義爲 unicode 編碼,例如 a = u'你好'
  • 在 Python3中,全部系統平臺下字符串都表示爲 unicode 編碼,
  • 所以在編碼轉換時,一般須要以 unicode 做爲中間編碼,先將其餘編碼的字符串解碼(decode)成 unicode,再從 unicode 編碼(encode)成另外一種指定編碼。

 

UnicodeDecodeError 和 UnicodeEncodeError

環境:windows簡體中文 + Python2.7,當前環境 str 默認顯示編碼爲 gbk(Linux 環境中 Python2.7 默認顯示編碼爲 utf8)python

>>> a = ''
>>> a
'\xc4\xe3'
# 對應 gbk 編碼
>>> a.encode() UnicodeDecodeError: 'ascii' codec can't decode byte 0xc4 in position 0: ordinal not in range(128) # 當 a.encode() 執行時,python 解釋器發現 a 的編碼格式爲 GBK ,可是隻有 unicode 編碼才能進行 encode,因此係統幫咱們執行了 a.decode().encode() # 在 python2 中系統默認的 encoding 編碼爲 ascii,因此至關於 a.decode('ascii').encode('ascii') # 查看系統默認 encoding 編碼 >>> import sys >>> sys.getdefaultencoding() 'ascii' # 因 ascii 編碼中不支持中文字符,因此在執行到 decode時就出現了報錯 UnicodeDecodeError # 能夠將 a 解碼爲 unicode,再編碼爲 utf8格式 >>> a.decode('gbk') u'\u4f60' >>> a.decode('gbk').encode('utf8') '\xe4\xbd\xa0' #在 pyhton2 中定義 unicode 編碼的字符串 >>> b u'\u6211' >>> b.encode() UnicodeEncodeError: 'ascii' codec can't encode character u'\u6211' in position 0: ordinal not in range(128) # 在 python2 中系統默認的 encoding 編碼爲 ascii,因此至關於執行了 a.encode('ascii') # ascii 編碼中不支持中文字符,因此出現了UnicodeEncodeError # 能夠把字符串b編碼爲 uft8 或者 gbk 格式,由於這兩種編碼都支持中文字符 >>> b.encode('utf8') '\xe6\x88\x91' >>> b.encode('gbk') '\xce\xd2'

 

Python3 編碼

在 Python3 中字符串統一使用 unicode編碼,而且系統默認 encoding 爲 utf8windows

  • unicode 對內存操做友好,由於每個字符佔用的空間同樣
  • utf-8對存儲和傳輸友好,由於會對應的減小佔用空間的大小
>>> import sys
>>> print(sys.getdefaultencoding())
utf-8

>>> a = "你好" >>> a.encode() b'\xe4\xbd\xa0\xe5\xa5\xbd'

>>> a.encode().decode() '你好' >>> a.encode('gbk').decode('gbk') '你好'

 

 

相關文章
相關標籤/搜索