最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

python黑魔法之編碼轉(zhuǎn)換

 更新時間:2016年01月25日 16:09:28   作者:icedoom  
這篇文章主要介紹了python黑魔法之編碼轉(zhuǎn)換,分析了python編碼轉(zhuǎn)換的方法,感興趣的小伙伴們可以參考一下

我們在使用其他語言的庫做編碼轉(zhuǎn)換時,對于無法理解的字符,通常的處理也只有兩種(或三種):

  • 拋異常
  • 替換成替代字符
  • 跳過

但是在復(fù)雜的現(xiàn)實世界中,由于各種不靠譜,我們處理的文本總會出現(xiàn)那么些不和諧因素,比如混合編碼。在這種情況下,又回到了上面的處理辦法。

那么問題來了,python有沒有更好地辦法呢?

答案是,有!

python的編碼轉(zhuǎn)換流程實際上是兩段式轉(zhuǎn)換:

source -> unicode -> dest

首先將字符串從原始編碼轉(zhuǎn)換成unicode。再將unicode轉(zhuǎn)換成目標(biāo)編碼。

第一步我們一般采用decode()或者 unicode() 這兩個函數(shù)完成。
第二步我們使用encode()函數(shù)完成。

在這里我們說的黑魔法就是在第一步實現(xiàn)。

decode和unicode函數(shù)都有一個叫做errors的可選參數(shù)??纯垂俜降拿枋觯?/p>

  • errors may be given to set a different error
  • handling scheme. Default is 'strict' meaning that encoding errors raise
  • a UnicodeDecodeError. Other possible values are 'ignore' and 'replace'
  • as well as any other name registered with codecs. register_error that is
  • able to handle UnicodeDecodeErrors.

這個參數(shù)通常有三種值:

  • strict 默認(rèn)值。如果出現(xiàn)編碼錯誤,則會拋出UnicodeDecodeError。
  • ignore 跳過。
  • replace 用?替換。

好了,看到最后一句話了嗎?好戲上演了!

模塊codec有一個函數(shù)叫做register_error。他的作用讓用戶可以注冊自定義的errors處理方法。
用來處理UnicodeDecodeError。

我們看看函數(shù)原型:

codecs.register_error(name, error_handler)

name: 錯誤處理的名稱。用以填寫在decode函數(shù)的error參數(shù)中。
error_handler: 處理函數(shù)。該函數(shù)接受一個異常參數(shù)。
返回一個tuple,該tuple有2個元素,第一個是糾錯后的字符串,第二個是繼續(xù)decode的起始位置

有了上面的基本概念。我們看下具體實現(xiàn):

def cjk_error(e):
  if not isinstance(e, UnicodeDecodeError):
    raise TypeError("don't know how to handle %r" % exc) 
  if exc.end + 1 > len(exc.object): 
    raise TypeError('unknown codec ,the object too short!') 
  ch1 = ord(exc.object[exc.start:exc.end]) 
  newpos = exc.end + 1 
  ch2 = ord(exc.object[exc.start + 1:newpos]) 
  sk = exc.object[exc.start:newpos] 
  if 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0x7E<=ch2<=0xFE): # GBK 
    return (unicode(sk,'cp936'), newpos) 
  if 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0xA1<=ch2<=0xFE): # BIG5 
    return (unicode(sk,'big5'), newpos) 
  raise TypeError('unknown codec !') 
codecs.register_error("cjk_replace", cjk_replace) 

上面這個是我從網(wǎng)上copy的。開始我覺得很不錯,但是后來發(fā)現(xiàn)是個很不經(jīng)推敲的算法。
比如utf8和gbk在前兩個字節(jié)就有交集的部分。當(dāng)一個utf8的字符串以gbk編碼decode的時候,出現(xiàn)錯誤是從第三個字節(jié)開始(前兩個字節(jié)也能夠在gbk編碼范圍中對應(yīng)到一個漢字)。
如:

a = "你"              # utf8編碼:'\xe4\xbd\xa0'
c = unicode(a[:2],'gbk')  # 正常返回
c = unicode(a, 'gbk')    # UnicodeDecodeError 。錯誤發(fā)生在第三個字節(jié)

所以針對這種情況,做了下改進(jìn):

import codec

def cjk_replace(e):
  if not isinstance(e, UnicodeDecodeError):
    raise TypeError("invalid exception type %s" e)

  src = e.encoding
  if src in ('gbk','gb18030', 'big5'):
    beg = e.start - 2
    if beg >= 0:
      try:
        return unicode(e.object[beg:e.end], 'utf8'), e.end + 1
      except:
        pass

  if exc.end + 1 > len(exc.object):
    raise TypeError('unknown codec ,the object too short!')
  ch1 = ord(exc.object[exc.start:exc.end])
  newpos = exc.end + 1
  ch2 = ord(exc.object[exc.start + 1:newpos])
  sk = exc.object[exc.start:newpos]

  if src != 'gbk' and 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0x7E<=ch2<=0xFE): # GBK
    return (unicode(sk,'cp936'), newpos)
  if src != 'big5' and 0x81<=ch1<=0xFE and (0x40<=ch2<=0x7E or 0xA1<=ch2<=0xFE): # BIG5
    return (unicode(sk,'big5'), newpos)
  raise TypeError('unknown codec !')

codecs.register_error("cjk_replace", cjk_replace)

當(dāng)然,這個邏輯其實還是不夠嚴(yán)謹(jǐn)?shù)?。雖然對于這種混合編碼這種畸形活處理有點較真兒。
不過既然python提供這樣的能力,大家可以一起來討論下,我們怎么可以做的更好?

相關(guān)文章

  • Python查找算法之折半查找算法的實現(xiàn)

    Python查找算法之折半查找算法的實現(xiàn)

    這篇文章主要介紹了Python查找算法之折半查找算法的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 解決Python paramiko 模塊遠(yuǎn)程執(zhí)行ssh 命令 nohup 不生效的問題

    解決Python paramiko 模塊遠(yuǎn)程執(zhí)行ssh 命令 nohup 不生效的問題

    這篇文章主要介紹了解決Python paramiko 模塊遠(yuǎn)程執(zhí)行ssh 命令 nohup 不生效的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • 在Python中使用dict和set方法的教程

    在Python中使用dict和set方法的教程

    這篇文章主要介紹了在Python中使用dict和set方法的教程,dict字典是Python中的重要基礎(chǔ)知識,set與其類似,需要的朋友可以參考下
    2015-04-04
  • Python函數(shù)默認(rèn)參數(shù)設(shè)置的具體方法

    Python函數(shù)默認(rèn)參數(shù)設(shè)置的具體方法

    本文主要介紹了Python函數(shù)默認(rèn)參數(shù)設(shè)置,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • 使用jupyter notebook直接打開.md格式的文件

    使用jupyter notebook直接打開.md格式的文件

    這篇文章主要介紹了使用jupyter notebook直接打開.md格式的文件,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-04-04
  • Django項目打包完整步驟以及可能出現(xiàn)的問題

    Django項目打包完整步驟以及可能出現(xiàn)的問題

    django項目的結(jié)構(gòu)大體上都是類似,打包主要的功能就是把一些不需要部署的文件剔除,把需要部署的文件直接壓縮打包,下面這篇文章主要給大家介紹了關(guān)于Django項目打包完整步驟以及可能出現(xiàn)問題的相關(guān)資料,需要的朋友可以參考下
    2023-06-06
  • Python Unittest自動化單元測試框架詳解

    Python Unittest自動化單元測試框架詳解

    這篇文章主要為大家詳細(xì)介紹了Python Unittest自動化單元測試框架的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • Numpy數(shù)據(jù)轉(zhuǎn)換成image并保存的實現(xiàn)示例

    Numpy數(shù)據(jù)轉(zhuǎn)換成image并保存的實現(xiàn)示例

    本文主要介紹了Numpy數(shù)據(jù)轉(zhuǎn)換成image并保存的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-12-12
  • python生成多個只含0,1元素的隨機(jī)數(shù)組或列表的實例

    python生成多個只含0,1元素的隨機(jī)數(shù)組或列表的實例

    今天小編就為大家分享一篇python生成多個只含0,1元素的隨機(jī)數(shù)組或列表的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-11-11
  • 如何向scrapy中的spider傳遞參數(shù)的幾種方法

    如何向scrapy中的spider傳遞參數(shù)的幾種方法

    這篇文章主要介紹了如何向scrapy中的spider傳遞參數(shù)的幾種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11

最新評論

大余县| 客服| 城步| 新田县| 班戈县| 哈密市| 芜湖县| 湛江市| 和田市| 南城县| 柳江县| 太仓市| 壤塘县| 馆陶县| 方正县| 喀喇沁旗| 莱州市| 青海省| 敦化市| 交城县| 江山市| 通化市| 吴桥县| 高碑店市| 循化| 乐至县| 旬邑县| 揭阳市| 民权县| 万盛区| 兴海县| 临漳县| 康定县| 临汾市| 黑河市| 宝山区| 晋州市| 湟源县| 南江县| 桃源县| 崇文区|