1. 程式人生 > >一步一步搞定Python3.6編碼問題

一步一步搞定Python3.6編碼問題

python 編碼格式 unicodedecodeerror 字節流 字符流

Python中的編碼問題很蛋疼,我們遇到這類問題有時候會使用下面幾個步驟處理該問題:

1:這麽低級問題,別問同事了太丟人,趕緊百度;

2:臥槽,出了一堆廣告,罵個娘,趕緊找相關解決問題方式;

3:尼瑪,終於搞定,原來這麽簡單,趕緊搞定其它工作,晚上回頭在查原因;

4:傻B單位每天加班,到家都11點了,趕緊洗洗睡了;等會,先來局王者農藥......

5:編碼問題早就忘了;

6:過了幾天又出現編碼錯誤,技術分享,從第1步開始重新來過。


今天我們就花一局王者農藥時間搞定Python3.6的編碼問題。


  1. 搞清楚編碼格式:

    1)編碼格式:utf-8, gbk, gb2312, unicode...

    計算機和編碼關系:計算機如何顯示打印文字:中文,英文等。計算機不能識別字符,那麽它如何顯示?

    計算機可以讀取數據,於是我們前輩就弄一個字模,通過01標識把這個字符給他畫出來,然後使用一個二進制碼和這個字模對應起來,這樣,計算機就能根據這個二進制碼把這個字符顯示出來了。

    計算機 -> 編碼 -> 字模點陣 ->顯示,打印等。

    2)為什麽那麽多編碼格式?

    計算機是美國人發明的,他們只需要使用英文字符和常用符號,於是ascii(256)就足夠了;

    後來計算機普及了,中國人想讓處理漢字,日本人想讓他處理日文,阿拉伯人想讓他處理阿拉伯語,於是就有了各種編碼格式;比如gb2312,;但是gb2312表示一個字符需要2個字節,這樣表示一個英文字符有點浪費,於是大牛們整出了utf-8,utf-16等可變長編碼格式。

    出現了太多的編碼格式,讓人蛋疼,於是大牛們同意規範,又整出了unicode編碼格式,支持所有的語言。


    到這裏,可能明白編碼格式了。

    3)編寫一個txt文件,內容為:"中國",他存儲的是“中國”這個漢子麽,還是??

    1: 借助工具看一哈:

    技術分享

    文件內容:中國

    文件存儲內容:二進制數字:D6D0 B9FA

    文件編碼格式:gbk


    2:修改下軟件編碼格式:utf-8

    技術分享

    亂碼有麽有。

    為什麽亂碼?因為文字存儲編碼格式為gbk,我們指定軟件編碼格式utf-8,然後問題出現了:

    軟件去utf-8的編碼表裏找不到D6D0 B9FA對應的字模,或者找錯了,所以會亂碼。


  2. Python中編碼格式問題

    1:Python內置存儲格式為unicode

    2:字符流和字節流問題:

    1)字符流:程序內部使用,不能直接保存文件;str類型;

    2)字節流:保存文件,網絡傳輸;byte類型;

    3:Python中的編碼格式轉換


#Python3.6
>>> s = ‘中國‘
>>> s.decode(‘utf-8‘)
Traceback (most recent call last):
  File "<pyshell#21>", line 1, in <module>
    s.decode(‘utf-8‘)
AttributeError: ‘str‘ object has no attribute ‘decode‘
>>> u8 = s.encode(‘utf-8‘)
>>> u8
b‘\xe4\xb8\xad\xe5\x9b\xbd‘
>>> u8.encode(‘utf-8‘)
Traceback (most recent call last):
  File "<pyshell#24>", line 1, in <module>
    u8.encode(‘utf-8‘)
AttributeError: ‘bytes‘ object has no attribute ‘encode‘
>>> u8.decode(‘utf-8‘)
‘中國‘
>>>


python3.6版本中,s為unicode,是字符串類型,沒有decode方法,所以做解碼失敗;

u8是s使用utf-8編碼後的數據,沒有encode方法;

u8可以使用decode方法解碼成unicode,如果解碼格式為其它,我們可以看看結果:


>>> u8.decode(‘gbk‘)
Traceback (most recent call last):
  File "<pyshell#27>", line 1, in <module>
    u8.decode(‘gbk‘)
UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xad in position 2: illegal multibyte sequence

常見解碼錯誤:UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xad in position 2:

原因:u8的編碼格式是utf-8,我們使用gbk去解碼,造成該錯誤。

編碼格式之間轉換:(gb2312,utf-8...)->unicode ->(gb2312,utf-8...);

unicode是中間的橋梁。

4:文件打開問題(環境:window下):

將一個文本文件存儲為utf-8編碼,

>>> f = open(‘readme.txt‘)
>>> f.read()
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    f.read()
UnicodeDecodeError: ‘gbk‘ codec can‘t decode byte 0xbd in position 8: incomplete multibyte sequence

將文件打開,讀取的時候為什麽會有問題;

1)文件存儲形式字節,讀取的時候是字節,編碼格式為Utf-8

2)讀取文件時候,read方法會做一個解碼操作,但是他是什麽形式解碼呢?查看幫助文檔:

>>> help(open)
Help on built-in function open in module io:

open(file, mode=‘r‘, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
    Open file and return a stream.  Raise IOError upon failure.
    .....
>>> f
<_io.TextIOWrapper name=‘readme.txt‘ mode=‘r‘ encoding=‘cp936‘>

這裏可以看到,f的編碼格式"cp936",這個和gbk是一樣的編碼格式,到這裏知道為啥會出錯了吧,文件存儲字節是utf-8編碼,解碼使用gbk方式,所以會出錯,在open的時候指定編碼格式utf-8再來一次試試:

>>> f = open(‘readme.txt‘, encoding=‘utf-8‘)
>>> line = f.readline()
>>> line
‘\ufeff中國‘
>>> print (line)
中國

讀取成功,"\ufeff"是window下utf-8文件編碼格式頭。到這裏我們就基本搞清楚常見的編碼問題了。

5:文件存儲問題:

一個栗子:

>>> f = open(‘test.txt‘, ‘w‘)
>>> f.write(‘中國‘)
>>> f.close()

傳的參數為字符流,但實際存儲為字節流,

>>> f = open(‘test.txt‘, ‘rb‘)
>>> f.read()
b‘\xd6\xd0\xb9\xfa‘

自己搞搞:使用utf-8方式打開test.txt, 然後讀取出現什麽問題?


好了到這裏,編碼基本就到這裏,如果還有不清楚的可以參考俺的視頻課程:

http://edu.51cto.com/course/8983.html,第二章內容。

另外,俺的水平有限,如果錯誤歡迎指正。

本文出自 “編程人生” 博客,請務必保留此出處http://huangyg.blog.51cto.com/1744433/1957295

一步一步搞定Python3.6編碼問題