Python 3中的編碼


Python 3中的默認編碼

Python3中默認是UTF-8

可查看Python3的默認編碼。

>>> import sys
>>>
>>> sys.getdefaultencoding()
'utf-8'
>>>

 

系統默認編碼 指:
在python 3編譯器讀取.py文件時,若沒有頭文件編碼聲明,則默認使用“utf-8”來對.py文件進行解碼。並且在調用 encode()這個函數時,不傳參的話默認是“ utf-8 ”。(這與下面的open( )函數中的“encoding”參數要做區分

本地默認編碼 指:
在你編寫的python 3程序時,若使用了 open( )函數 ,而不給它傳入 “ encoding ” 這個參數,那么會自動使用本地 Windows 或 Linux 的默認編碼。沒錯,如果在Windows系統中,就是默認用gbk格式所以請大家在這里注意:linux中可以不用傳“ encoding” 的參數, 而win中不能忘了“ encoding” 的參數

 

utf-8是可變長的的編碼,有1個字節的英文字符,也有2個字節的阿拉伯文,也有3個字節的中文和日文。utf-8是有嚴格定義的,一個字節的字符高位必須是0;三個字節的字符中,第一個字節的高位是1110開頭。   
    
gbk對英文是使用單字節編碼(也就意味着兼容ascii),而gbk對中文部分是采取定長的2字節,總體編碼范圍為 8140-FEFE,首字節在 81-FE 之間,尾字節在 40-FE 之間。所以說它只要沒有碰到尾字節在40之內的字符,都會一股腦地按照2字節去解碼成中文。而中文在 utf-8 編碼后,一般是三字節的。當解碼的字節數和編碼的字節數不匹配時,自然會造成全是亂碼的局面。

 

實際上unicode就是一個字符集,一個字符與數字一一對應的映射關系,因為它一律以2個字節編碼(或者也有4個字節的,這里不討論),所以占用空間會大一些,一般只用於內存中的編碼使用。
而 utf-8 是為了實現unicode 的傳輸和存儲的。因為它可變長,存英文時候可以節省大量存儲空間。傳輸時候也節省流量。

進程在內存中的表現是“ unicode ”的編碼;當python3編譯器讀取磁盤上的.py文件時,是默認使用“utf-8”的;當進程中出現open(), write() 這樣的存儲代碼時,需要與磁盤進行存儲交互時,則是默認使用操作系統的默認編碼。

 

 

 

Python 3中的​encode和decode

Python3中字符編碼經常會使用到decode和encode函數。特別是在抓取網頁中,這兩個函數用的熟練非常有好處。encode的作用,使我們看到的直觀的字符轉換成計算機內的字節形式。decode剛好相反,把字節形式的字符轉換成直觀的形式。

>>> "西安".encode()
b'\xe8\xa5\xbf\xe5\xae\x89'
>>> b'\xe8\xa5\xbf\xe5\xae\x89'.decode()
'西安'

\x表示后面是十六進制

在Python 3中, 以字節形式表示的字符串則必須加上前綴b,也就是寫成上文的b'xxxx'形式。

 ​UTF-8兼容ASCII

 

Python3中的​編碼轉換

 字符以Unicode的字節形式表現出來

>>> "西安".encode('unicode-escape')
b'\\u897f\\u5b89'
>>> b'\\u897f\\u5b89'.decode('unicode-escape')
'西安'

如果我們知道一個Unicode字節碼,怎么變成UTF-8的字節碼,先decode,再encode。

>>> "西安".encode('unicode-escape')
b'\\u897f\\u5b89'
>>> "西安".encode('unicode-escape').decode('unicode-escape')
'西安'
>>> "西安".encode('unicode-escape').decode('unicode-escape').encode()
b'\xe8\xa5\xbf\xe5\xae\x89'

 

 

源代碼文件中,如果有用到非ASCII字符,則需要在文件頭部進行字符編碼的聲明,如下:

#-*- coding: UTF-8 -*-

   

 python3中的字符序列也有兩種類型:bytes和str。python3中的bytes和python2中的str相似,str和python2中的unicode相似。這里要注意,str類型在python3和python2中都有,但含義完全變了。

unicode_string=u'中國'
print(len(unicode_string))
print( type(unicode_string))
str_string = unicode_string.encode('utf-8')
print(len(str_string))
str_string
print(type(str_string))


>>> unicode_string=u'中國'
>>> print(len(unicode_string))
2
>>> print( type(unicode_string))
<class 'str'>
>>> str_string = unicode_string.encode('utf-8')
>>> print(len(str_string))
6
>>> str_string
b'\xe4\xb8\xad\xe5\x9b\xbd'
>>> print(type(str_string))
<class 'bytes'>

 

UnicodeEncoderError
將文本轉化為字節序列時,若有字符在目標編碼中沒有定義,則會出現UnicodeEncoderError。
由於中文字符在ascii編碼中無定義,則會報出編碼錯誤。對於此類問題,需選擇合適的編碼類型,比如含有中文字符,一般用UTF-8編碼類型對unicode字符串編碼。

>>> unicode_string=u'平國'
>>> unicode_string.encode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

 



UnicodeDecodeError
把二進制序列轉化為文本時,遇到無法轉換的字節序列,則會發生此異常。比如用UTF-8編碼后的二進制序列,用GB2312解碼,由於兩種編碼不兼容,用GB2312不能識別字節序列,則會出現異常。

unicode_string=u'中國'
utf8_string=unicode_string.encode('utf-8')
utf8_string.decode('GB2312')

 



碰到這種異常,是由於decode使用的編碼和字節序列的編碼不一致,可以用字符編碼偵測包chardet檢測字節序列的編碼,然后再用此編碼解碼。

import chardet  ### pip install chardet
utf8_string=u"中國"
str_type=chardet.detect(utf8_string)
str_type

 

#python 3,str和bytes類型相互轉換工具類
#file:python3_endecode_helper.py
def to_str(bytes_or_str):
    if isinstance(bytes_or_str,bytes):
        value = bytes_or_str.decode('UTF-8')
    else:
        value = bytes_or_str
    return value

def to_bytes(bytes_or_str):
    if isinstance(bytes_or_str,str):
        value = bytes_or_str.encode('UTF-8')
    else:
        value = bytes_or_str
    return value

if __name__=='__main__':
    str_string = u'中國'
    value = to_bytes(str_string)
    print(type(value)) #<class 'bytes'>
    value = to_str(value)
    print(type(value)) #<class 'str'>

 



 

# coding:gbk

import sys
import locale

def p(f):
    print('%s.%s(): %s' % (f.__module__, f.__name__, f()))

# 返回當前系統所使用的默認字符編碼
p(sys.getdefaultencoding)

# 返回用於轉換Unicode文件名至系統文件名所使用的編碼
p(sys.getfilesystemencoding)

# 獲取默認的區域設置並返回元組(語言, 編碼)
p(locale.getdefaultlocale)

# 返回用戶設定的文本數據編碼
# 文檔提到this function only returns a guess
p(locale.getpreferredencoding)

# 在筆者的Windows上的結果
# sys.getdefaultencoding(): utf-8
# sys.getfilesystemencoding(): utf-8
# locale.getdefaultlocale(): ('en_US', 'cp936')
# locale.getpreferredencoding(): cp936

 

 

REF

https://www.cnblogs.com/killianxu/p/9746545.html

https://www.cnblogs.com/huxi/archive/2010/12/05/1897271.html

https://blog.csdn.net/ym01213/article/details/89083428

https://zhuanlan.zhihu.com/p/40834093


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM