徹底搞懂python字符編碼,看這篇就夠了!

2021-02-14 Python測試自動化

不論你是有著多年經驗的 Python 老司機還是剛入門 Python 不久,你一定遇到過UnicodeEncodeError、UnicodeDecodeError 錯誤,每當遇到錯誤我們就拿著 encode、decode 函數翻來覆去的轉換,有時試著試著問題就解決了,有時候怎麼試都沒轍,只有借用 Google,百度各種 大神幫忙,但似乎很少去關心問題的本質是什麼,下次遇到類似的問題重蹈覆轍,那麼你有沒有想過一次性徹底把 Python 字符編碼給搞懂呢?

字符編碼是計算機的基石,想要熟練使用計算機,就必須懂得一點字符編碼的知識,首先我們來說說字符編碼,這其實與是哪種語言並無太大聯繫,首先我們來了解幾個基本概念

字符集

字符集(Character Set)就是某個範圍內字符的集合,不同的字符集規定了字符的個數,比如 ASCII 字符集總共有128個字符,包含了英文字母、阿拉伯數字、標點符號和控制符。而 GB2312 字符集定義了7445個字符,包含了絕大部分漢字字符。

字符碼

字符碼(Code Point)指的是字符集中每個字符的數字編號,例如 ASCII 字符集用 0-127 連續的128個數字分別表示128個字符,例如 "A" 的字符碼編號就是65。

字符編碼

字符編碼(Character Encoding)是將字符集中的字符碼映射為字節流的一種具體實現方案,常見的字符編碼有 ASCII 編碼、UTF-8 編碼、GBK 編碼等。某種意義上來說,字符集與字符編碼有種對應關係,例如 ASCII 字符集對應 有 ASCII 編碼。ASCII 字符編碼規定使用單字節中低位的7個比特去編碼所有的字符。例如"A" 的編號是65,用單字節表示就是0×41,因此寫入存儲設備的時候就是b'01000001'。

編碼(encode)、解碼(decode)

編碼的過程是將字符串轉換成字節流,解碼的過程是將字節流解析為字符串。

理解了這些基本的術語概念後,我們就可以開始討論計算機的字符編碼的演進過程了。

字符編碼演進

一、ASCII碼

我們知道在計算機的內部所有信息最終都是二進位值,每一個二進位位(bit)有0和1兩種狀態,因此八個二進位位就可以組成256種狀態,這樣的組合被稱之為一個字節(byte),一個字節用來表示256種不同的狀態,每個狀態對應一種符號,從00000000到11111111。
基於以上,美國也制定了一套字符編碼,用來制定英語字符與二進位位之間的關係,就被稱之為ASCII碼,比如大寫字母A的編碼是65,小寫字母z的編碼是122

英語用128個編碼就夠了,但是用來表示歐洲其他語言,顯然就不夠了,即使是歐洲國家擴充到256個,但是每個國家可能每個字母對應的含義都不一樣,至於到亞洲國家的文字,那顯然就更不夠用了,光中文就是上萬字

正如這樣世界上存在著各種編碼方式,並且同一個二進位數字可以被解釋成為不同的符號,因此要打開一個文件,必須提前知道它的字符編碼,否則就會產生亂碼,正是這種背景,unicode應運而生,正如它名字一般,這是一種所有符號的編碼,這樣也就不會有亂碼問題了

需要注意的是,Unicode 只是一個符號集,它只規定了符號的二進位代碼,卻沒有規定這個二進位代碼應該如何存儲。現在,捋一捋ASCII編碼和Unicode編碼的區別:ASCII編碼是1個字節,而Unicode編碼通常是2個字節。字母A用ASCII編碼是十進位的65,二進位的01000001;字符0用ASCII編碼是十進位的48,二進位的00110000,注意字符'0'和整數0是不同的;漢字中已經超出了ASCII編碼的範圍,用Unicode編碼是十進位的20013,二進位的01001110 00101101。你可以猜測,如果把ASCII編碼的A用Unicode編碼,只需要在前面補0就可以,因此,A的Unicode編碼是00000000 01000001。

新的問題又出現了:如果統一成Unicode編碼,亂碼問題從此消失了。但是,如果你寫的文本基本上全部是英文的話,用Unicode編碼比ASCII編碼需要多一倍的存儲空間,在存儲和傳輸上就十分不划算。

三、UTF-8

基於以上出現了UTF-8 ,這裡要重要提出來的是,UTF-8是unicode的實現方式之一,UTF-8的最大的特點是:它是一種變長的編碼方式,使用1~4個字節表示一個符號,根據不同的符號而變化編碼長度,

UTF-8 的編碼規則很簡單,只有二條:

1)對於單字節的符號,字節的第一位設為0,後面7位為這個符號的 Unicode 碼。因此對於英語字母,UTF-8 編碼和 ASCII 碼是相同的。

2)對於n字節的符號(n > 1),第一個字節的前n位都設為1,第n + 1位設為0,後面字節的前兩位一律設為10。剩下的沒有提及的二進位位,全部為這個符號的 Unicode 碼。

下表總結了編碼規則

Unicode符號範圍        |        UTF-8編碼方式(十六進位)             |              (二進位)--+0000 0000-0000 007F   |         0xxxxxxx0000 0080-0000 07FF   |         110xxxxx 10xxxxxx0000 0800-0000 FFFF   |         1110xxxx 10xxxxxx 10xxxxxx0001 0000-0010 FFFF   |         11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

搞清楚了ASCII、Unicode和UTF-8的關係,我們就可以總結一下現在計算機系統通用的字符編碼工作方式:

在計算機內存中,統一使用Unicode編碼,當需要保存到硬碟或者需要傳輸的時候,就轉換為UTF-8編碼。

用記事本編輯的時候,從文件讀取的UTF-8字符被轉換為Unicode字符到內存裡,編輯完成後,保存的時候再把Unicode轉換為UTF-8保存到文件:

瀏覽網頁的時候,伺服器會把動態生成的Unicode內容轉換為UTF-8再傳輸到瀏覽器:

所以你看到很多網頁的源碼上會有類似<meta charset="UTF-8" />的信息,表示該網頁正是用的UTF-8編碼。

搞清楚了字符編碼的一些基本類型後,我們來說說python的字符串

python2 中和字符串相關的數據類型有 str 和 unicode 兩種類型,它們繼承自 basestring,而 str 類型的字符串的編碼格式可以是 ascii、utf-8、gbk等任何一種類型。

在字符編碼轉換操作時,遇到的最多的就是UnicodeEncodeError 和UnicodeDecodeError 錯誤,這些錯誤的根本原因在於python2默認使用ascii編碼進行decode和encode操作,由於目前python版本基本都是以python3為主,所以亂碼等由於編碼不一致的問題都好解決了了

在最新的Python 3版本中,字符串是以Unicode編碼的,也就是說,Python的字符串支持多語言,例如:

>>> import sys>>> print(sys.getdefaultencoding())utf-8>>> print('包括中文也很好支持')包括中文也很好支持

對於單個字符的編碼,Python提供了ord()函數獲取字符的整數表示,chr()函數把編碼轉換為對應的字符:

>>> ord('Z')90>>> ord('熊')29066>>> chr(29066)'熊'

 python3中,str是unicode,當程序執行時,無需加u,str也會被以unicode形式保存新的內存空間中,str可以直接encode成任意編碼格式,s.encode('utf-8'),s.encode('gbk')

#unicode(str)encode---->utf-8(bytes)
#utf-8(bytes)decode---->unicode

好了今天就到這了,算是對python字符編碼的一個總結吧,如果覺得對你有幫助,別忘了告訴我哦,也算是對我的一種鼓勵

相關焦點

  • 徹底搞懂這煩人的編碼與亂碼!
    ❝我們平時在處理文本文件或者網絡請求時,時不時會遇到亂碼的情況,這篇文章就帶你徹底搞懂編碼和亂碼❞首先,我們要知道,在計算機中,一切都是用0和1來表示的。普通的txt文件、或者客戶端發過來的數據等等,這些一切其實都是通過0和1轉化而來的。「那它是怎樣從0和1轉化我們人能看懂的字母或漢字呢?」
  • Python : 熟悉又陌生的字符編碼
    常見的字符編碼有 ASCII 編碼,UTF-8 編碼,GBK 編碼等。一般而言,字符集和字符編碼往往被認為是同義的概念,比如,對於字符集 ASCII,它除了有「字符的集合」這層含義外,同時也包含了「編碼」的含義,也就是說,ASCII 既表示了字符集也表示了對應的字符編碼。
  • Python 2.x 字符編碼終極指南
    但僅了解這篇文章的內容,並不能幫我們在日常編程中躲過一些字符編碼相關的坑,Stackoverflow 上就有大量編碼相關的問題,比如 1,2,3。本文首先嘗試對編碼、解碼進行一個宏觀、直觀的解讀,然後詳細來解釋 python2 中的str和unicode,並對常見的UnicodeEncodeError 和 UnicodeDecodeError 異常進行剖析。
  • 那就看進來! 一文搞懂 Python 2 字符編碼
    計算機發源於美國,使用的是英文字母(字符),所有26個字母的大小寫加上數字0到10,加上符號和控制字符,總數也不多,用一個字節(8個bit)就能表示所有的字符,這就是ANSI的「Ascii」編碼(American Standard Code for Information Interchange,美國信息互換標準代碼)。
  • Python: 熟悉又陌生的字符編碼
    常見的字符編碼有 ASCII 編碼,UTF-8 編碼,GBK 編碼等。一般而言,字符集和字符編碼往往被認為是同義的概念,比如,對於字符集 ASCII,它除了有「字符的集合」這層含義外,同時也包含了「編碼」的含義,也就是說,ASCII 既表示了字符集也表示了對應的字符編碼。
  • 徹底搞懂字符編碼
    背景在日常開發中很少接觸到字符的概念,大部分語言對字符的轉換都已經封裝的足夠好,不需要開發人員過多考慮編碼解碼的問題。
  • 不得不知道的Python字符串編碼相關的知識
    由於之前不知道編碼的原理,遇到這些情況,就只能不斷的用各種編碼decode和encode。。。。。今天整理一個python中的各種編碼問題的原因和解決方法,以後遇到編碼問題,就不會像莽頭蒼蠅一樣,到處亂撞了。下面的python環境都是在2.7,聽說在3.X中已經沒有編碼的問題了,因為所有的字符串都是unicode了,之後裝個3.X試一下。
  • 本地化入門 | 不懂「字符集」和「字符編碼」?讀這篇就夠了!
    因為同一個字符集只有一種編碼方式,如ASCII既可以指代字符集也可以指代字符編碼。而Unicode字符集出現後,由於它支持多種編碼方式,才開始區分這兩者。在Unicode下,字符集指的是Unicode,字符編碼則指UTF-8、UTF-16、UTF-32等。
  • Python 編碼錯誤的本質原因
    點擊上方藍字,快速關注我們)來源:伯樂在線 - 劉志軍foofish.net/python-unicode-error.html
  • Python編程中的字符串編碼轉換問題
    介紹1.1 介紹福哥今天給大家講講關於Python編程中的字符串編碼轉換的問題,這個問題在初學者編程時候會經常遇到,如果要弄清楚這裡面的道道,還是需要好好學習一下的2.所以,python在進行編碼轉換時候都是先用decode轉為unicode,再用encode轉為目標編碼3. IDLE編碼在編輯器裡定義的字符串常量也是有編碼設置的,這個編碼可以通過腳本「頁頭」進行聲明3.1 聲明方法在腳本頁頭使用coding指定腳本默認編碼
  • Python3 是如何解決棘手的字符編碼問題的?
    題圖:unsplash.comPython3 最重要的一項改進之一就是解決了 Python2 中字符串與字符編碼遺留下來的這個大坑。str>>> a = "a">>> a'a'>>> type(a)<class 'str'>>>> b = "禪">>> b'禪'>>> type(b)<class 'str'&
  • 關於計算機編碼這篇就夠了
    2.關鍵詞信息,載體,編碼,解碼,規範 位,字節,字符,字符串(字符集), 伺服器,瀏覽器(meta charset),文本編輯器,文本編碼,亂碼,數字編碼,補碼原理3.全文概要本文從信息表示作為開端講起,由淺及深列出各種程式設計師熟視無睹而且模糊不清的概念。試圖深入剖析個中由來,理清計算機底層概念模型,從而加深對計算機基礎的認識。
  • 幫你徹底弄懂常見的中文字符編碼
    | 導語 本文主要介紹了業務中常見的ASCII、GB2312、GBK、GB18030、UTF8、ANSI、Latin1中文編碼。
  • Python 3 入門,看這篇就夠了
    /usr/bin/env python,那麼可以在命令行窗口中執行/path/to/script-file.py以執行該腳本文件。註:該方法不支持 Windows 環境。編碼默認情況下,3.x 源碼文件都是 UTF-8 編碼,字符串都是 Unicode 字符。
  • Python正則表達式,看完這篇文章就夠了!
    https://www.runoob.com/regexp/regexp-tutorial.htmlhttps://tool.oschina.net/regex/https://goregex.cn/https://docs.python.org
  • python正則表達式,看完這篇文章就夠了...
    作者:王翔丨公眾號:清風Python正則表達式這東西,你說它簡單它也簡單,你說它難吧,確實不容易。為什麼?這東西就是死記硬背的。網上關於python正則的帖子很多,我再去寫壓力比較大,儘可能的總結詳細一些吧!正則表達式,是一個特殊的字符序列,又稱規則表達式(英語:Regular Expression,在代碼中常簡寫為regex、regexp 或RE),本質而言是一種小型的,高度專業化的程式語言。Python 自1.5版本起增加了re 模塊,re 模塊使Python語言擁有全部的正則表達式功能。
  • 建議收藏,徹底搞懂字符編碼問題,從此告別中文亂碼
    在沒有深入理解其原理之前,會覺得中文編碼問題比較謎,莫名其妙地亂碼,又稀裡糊塗地好了。字符編碼是計算機技術的基石,本文希望幫助大家徹底梳理清楚字符編碼問題,不僅知其然,還知其所以然,擺脫被中文亂碼支配的感覺。在講解中文編碼問題之前,我們需要先講講英語編碼,其解決方案是 ASCII。
  • Python讀寫文件編碼的一個小問題
    反編譯完基本上就是源碼文件了,這不是本篇文字的重點,重點是因為源碼文件中有中文字符,反編譯出來的源碼文件就成了\x十六進位亂碼模式。那就自己寫代碼解決這個問題吧,從原理上來說把一串\x編碼轉成中文實際很簡單(這是在Python 2.7執行環境中運行),像下面這樣>>> s1 = "\xe6\x97\xa7\xe8\xb7\xaf\xe5\xbe\x84\xe5\xb7\xa5\xe7\xa8\x8b\xe6\x89\x93\xe5\x8c\x85">
  • 字符編碼那些事兒
    英語用128個符號編碼就夠了,但是用來表示其他語言,128個符號是不夠的。比如在法語中,字母上方有注音符號,它就無法用ASCII碼表示。於是,一些歐洲國家就決定,利用字節中閒置的最高位編入新的符號。比如,法語中的é的編碼為130(二進位10000010)。
  • Python高效編程之88條軍規(1):編碼規範、字節序列與字符串
    為了將文本編碼數據轉換為二進位數據,必須調用字符串的encode方法。為了將二進位數據轉換為文本編碼數據,必須調用字節序列的decode方法。我們可以顯式地指定這些方法的編碼格式,或者接受這些方法的默認編碼格式。默認編碼格式通常是UTF-8,不過也並不是所有方法的默認編碼格式都是UTF-8,具體情況請看下面的內容。