Python直與編碼

黄舟
發布: 2016-12-16 11:34:24
原創
1209 人瀏覽過

Python中的文字物件

Python 3.x中處理文字的物件有str, bytes, bytearray。

bytes和bytearray可以使用除了用作格式化的方法(format, format_map)以及幾個特殊的基於Unicode的方法(casefold, isdecimal, isidentifier, isnumeric, isPRintable, encode)以外幾乎所有str的方法。

bytes有一個類別方法,可以透過序列來建構字串,而這個方法不可以用在str上。

>>> b = bytes.fromhex('E4 B8 AD')
>>> b
b'xe4xb8xad'
>>> b.decode('utf-8')
'中'
>>> b.decode('utf-8')
'中'
>>> str (b)

"b'\xe4\xb8\xad'"

Unicode和字符轉換

採用chr可以把一個Unicode的code point轉換為字符,透過ord可以進行反向操作。

>>> ord('A')
65
>>> ord('中')
20013
>>> chr(65)
'A'
>>> chr(20013)

'中'

'中'

'中'


len函數計算的是字元數,不是位元組數

>>> len('中')
1
>>> '中'.encode('utf-8')
b'xe4xb8xad'

> >> len('中'.encode('utf-8'))    #計算的是bytes物件的長度,包含3個整數字元

3

Python與編碼


Python內部處理編碼的方式
Python與編碼

Python內部處理編碼的方式

Python接受我們的輸入時,總是會先轉為Unicode。而且這個過程越早越好。

接著Python的處理總是對Unicode進行的,在這個過程中,一定不要進行編碼轉換的工作。
在Python向我們回傳結果時,總是會從Unicode轉為我們需要的編碼。而且這個過程越晚越好。

Python源碼的編碼方式

Python預設使用utf-8編碼。

如果想要使用不同的編碼方式來保存Python程式碼,我們可以在每個檔案的第一行或第二行(如果第一行被hash-bang指令佔用了)放置編碼宣告(encoding declaration)
# ‐*‐ coding: windows‐1252 ‐*‐

Python中使用的編碼

C:UsersJL>chcp        #) 使用的編碼
>使用的編碼> locale.getpreferredencoding()    #這個是最重要的
'cp936'
>>> my_file = open('cafe.txt','r')
>>> type(my_file)

>>> my_file.encoding    #檔案物件預設使用locale.getpreferreddecoding()的值
'cp936'
>>>> sys.stdout.isatty(), sys.stdin.isa(), sys.sysstderr.isa(tty( )    #output是否為控制台console
(True, True, True)
>>> sys.stdout.encoding, sys.stdin.encoding, sys.stderr.encoding    #sys的標準控制流若被重新導向,或定向定向到文件,那麼編碼將使用環境變數PYTHONIOENCODING的值、控制台console的編碼、或locale.getpreferredencoding()的編碼,優先順序依次減弱。
('cp936', 'cp936', 'cp936')
>>> sys.getdefaultencoding()    #如果Python需要把二進位資料轉為字元對象,那麼在缺省情況下使用該值。
'utf-8'

>>> sys.getfilesystemencoding()    #Python用來編碼或解碼檔案名稱(不是檔案內容)的時候,預設使用該編碼。

'mbcs'

以上是在Windows中的測試結果,如果在GNU/linux或OSX中,那麼所有的結果都是UTF-8.

關於mbcs和utf-8的區別,可以參考http:/ /stackoverflow.com/questions/3298569/difference-between-mbcs-and-utf-8-on-windows


檔案讀寫的編碼

>>> pen('cafe.txt','w',encoding= 'utf-8').write('café')
4
>>> fp = open('cafe.txt','r')
>>> fp.read()
'caf茅'
>> > fp.encoding
'cp936'
>>> open('cafe.txt','r', encoding = 'cp936').read()
'caf茅'
>>> open('cafe.txt' ,'r', encoding = 'latin1').read()
'café'
>>> fp = open('cafe.txt','r', encoding = 'utf-8')

>>>> fp.encoding🎜'utf-8'🎜🎜

從上面的例子可以看出,無論何時都不要使用預設的編碼,因為在不同的機器上運行的時候會出現意想不到的問題。

Python如何處理來自Unicode的麻煩

Python總是透過code point來比較字串的大小,或是相等的。

Unicode中重音符號有兩種表示方法,用一個位元組表示,或用基底字母加上重音符號表示,在Unicode中他們是相等的,但是在Python中由於透過code point來比較大小,所以就不相等了。

>>> c1 = 'cafeu0301'
>>> c2 = 'café'
>>> c1 == c2
False
>>> len(c1), len(c2)
False
>>> len(c1), len(c2)

False

>>> len(c1), len(c2)
(5, 4)
(5
解決方法是透過unicodedata庫中的normalize函數,該函數的第一個參數可以接受"NFC",'NFD','NFKC','NFKD'四個參數中的一個。
NFC(Normalization Form Canonical Composition):以標準等價方式來分解,然後以標準等價重組之。若是singleton的話,重組結果有可能和分解前不同。盡可能的縮短整個字串的長度,所以會把'eu0301'2個位元組壓縮到一個位元組'é'。
NFD(Normalization Form Canonical Decomposition):以標準等價方式來分解

NFKD(Normalization Form Compatibility Decomposition):以相容等價方式來分解

NFKC(Normalization Form Compatibility Composition):以等價方式分解相容方式,然後以標準等價重組之。
NFKC和NFKD可能會造成資料損失。

from unicodedata import normalize
>>> c3 = normalize('NFC',c1)        #把c1往字串長度縮短的方向運算
>>> len(c3)
> True
>>> c4 = normalize('NFD',c2)
>>> len(c4)
5
>>> c4 == c1
True

西方的鍵盤通常會鍵入盡可能短的字串,也就是說和"NFC"的結果一致,但是透過"NFC"來操作一下再比較字串是否相等比較安全。且W3C建議使用"NFC"的結果。


同樣的一個字元在Unicode中有兩個不同的編碼。

這個函數會把一個單一的Unicode字元轉為另一個Unicode字元。


>>> o1 = 'u2126'
>>> o2 = 'u03a9'
>>> o1, o2
('Ω', 'Ω')
>>> o1 == o2
False>
>
> name(o1), name(o2)
('OHM SIGN', 'GREEK CAPITAL LETTER OMEGA')
>>> o3 = normalize('NFC',o1)
>>> name(o3)
'GREEK CAP OMEGA'
>>> o3 == o2

True

又例如

>>> u1 = 'u00b5'
>>> u2 = 'u03bc'
>>>> μ')
>>> name(u1), name(u2)
('MICRO SIGN', 'GREEK SMALL LETTER MU')
>>> u3 = normalize('NFKD',u1)
>>> name( u3)
'GREEK SMALL LETTER MU'

再一個例子


>>> h1 = 'u00bd'
>>> h2 = normalize('NFKC',h1)
>>½> ', '1⁄2')
>>> len(h1), len(h2)
(1, 3)

有時候我們希望使用不區分大小寫的形式進行比較
使用方法str.casefold( ),此方法會將大寫字母轉換為小寫進行比較,例如'A'會轉為'a','MICRO SIGN'的'µ'會轉換為'GREEK SMALL LETTER MU'的'µ'
在絕大部分(98.9%)情況下str.casefold()和str.lower()的結果一致。

文字排序
由於不同的語言規則,如果單純按照Python的比較code point的方式進行,那麼會出現很多不是用戶期望的結果。
通常會採用locale.strxfrm進行排序。

>>> import locale
>>> locale.setlocale(locale.LC_COLLATE,'pt_BR.UTF-8')
'pt_BR.UTF-8'
>>> sort_result = coperat(intial, 片 =>> )

編碼解碼錯誤

如果是Python源碼中出現了解碼錯誤,那麼會產生SyntaxError異常。
其他情況下,如果發現編碼解碼錯誤,那麼會產生UnicodeEncodeError, UnicodeDecodeError異常。

幾個摘自fluent python中的有用方法

from unicodedata import normalize,組合
def nfc_equal(s1, s2):
   '''如果在「NFC」下標準化後字串s1 等於字串s2,則傳回True '''
 s1) = = normalize("NFC",s2)

def Fold_equal(s1, s2):
   '''如果在「NFC」和casefold() 下標準化後字串s1 與字串s2 相等,則傳回True '''
   return normalize( 'NFC',s1).casefold() == normalize('NFC',s2).casefold()

def shave_marks(txt):
 '''  所有變音🠎上只需要將拉丁文本改為純ASCII,但此函數也會更改希臘字母
   下面的shave_latin_marks 函數更精確'''

   normal_txt = normalize('NFD',)
   normal_txt = normalize('NFD',)
   shaved ( for c in normal_txt if not Combining( c))
   return normalize('NFC',shaved)

def shave_latin_marks(txt):
   '''刪除拉丁文基本字元中的所有變音符號 773):
('NFD',txt)
   keeping = []
   latin_base=False
   for c in normal_txt:
      if 結合(c) 與lat Ingore 變音符號
       keeping.append(c)
       #If it不是組合char,它應該是new base char
       如果沒有組合(c):
          素探測ython的標準模組。

參考資料:

http://blog.csdn. net/tctc/article/details/8191464

 以上就是python與編碼的內容,更多相關文章請關注PHPcn中文(www.php.. !

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板