欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

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

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

答案是,有!

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

source -> unicode -> dest

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

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

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

decode和unicode函數(shù)都有一個(gè)叫做errors的可選參數(shù)。看看官方的描述:

  • 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.

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

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

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

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

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

codecs.register_error(name, error_handler)

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

有了上面的基本概念。我們看下具體實(shí)現(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) 

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

a = "你"              # utf8編碼:'\xe4\xbd\xa0'
c = unicode(a[:2],'gbk')  # 正常返回
c = unicode(a, 'gbk')    # UnicodeDecodeError 。錯(cuò)誤發(fā)生在第三個(gè)字節(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)然,這個(gè)邏輯其實(shí)還是不夠嚴(yán)謹(jǐn)?shù)?。雖然對于這種混合編碼這種畸形活處理有點(diǎn)較真兒。
不過既然python提供這樣的能力,大家可以一起來討論下,我們怎么可以做的更好?

相關(guān)文章

  • 使用tensorflow將圖片灰度化以及遇到的坑解決

    使用tensorflow將圖片灰度化以及遇到的坑解決

    這篇文章主要介紹了使用tensorflow將圖片灰度化以及遇到的坑解決,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • pyMySQL SQL語句傳參問題,單個(gè)參數(shù)或多個(gè)參數(shù)說明

    pyMySQL SQL語句傳參問題,單個(gè)參數(shù)或多個(gè)參數(shù)說明

    這篇文章主要介紹了pyMySQL SQL語句傳參問題,單個(gè)參數(shù)或多個(gè)參數(shù)說明,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-06-06
  • 詳解Python中的strftime()方法的使用

    詳解Python中的strftime()方法的使用

    這篇文章主要介紹了詳解Python中的strftime()方法的使用,是Python入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-05-05
  • python中的decode()與encode()深入理解

    python中的decode()與encode()深入理解

    這篇文章主要介紹了python中的decode()與encode()函數(shù)詳解,本文通過實(shí)例代碼給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • 利用Python命令行傳遞實(shí)例化對象的方法

    利用Python命令行傳遞實(shí)例化對象的方法

    最近在工作中遇到了一個(gè)問題,需要接收啟動(dòng)腳本傳遞過來的實(shí)例化后的對象,通過在網(wǎng)上查找資料發(fā)現(xiàn)了兩個(gè)方法,文中通過實(shí)例代碼就給大家詳細(xì)介紹了這兩種方法,有需要的朋友們可以參考借鑒,下面來一起看看吧。
    2016-11-11
  • 5款最強(qiáng)且免費(fèi)的Python IDE小結(jié)

    5款最強(qiáng)且免費(fèi)的Python IDE小結(jié)

    開發(fā)工具在日常代碼編寫過程中起著至關(guān)重要的作用,一款優(yōu)秀的開發(fā)工具,不僅可以盡可能的減少你在配置方面耗費(fèi)的精力,本文主要介紹了5種,感興趣的可以了解一下
    2021-07-07
  • 如何將python項(xiàng)目部署在一臺服務(wù)器上

    如何將python項(xiàng)目部署在一臺服務(wù)器上

    服務(wù)器less技術(shù)是一種無需管理服務(wù)器即可運(yùn)行應(yīng)用程序的方法,最流行的服務(wù)器less平臺是AWS Lambda,這篇文章主要介紹了如何將python項(xiàng)目部署在一臺服務(wù)器上,需要的朋友可以參考下
    2023-10-10
  • 使用pyinstaller打包.exe文件的詳細(xì)教程

    使用pyinstaller打包.exe文件的詳細(xì)教程

    PyInstaller是一個(gè)跨平臺的Python應(yīng)用打包工具,能夠把 Python 腳本及其所在的 Python 解釋器打包成可執(zhí)行文件,下面這篇文章主要給大家介紹了關(guān)于使用pyinstaller打包.exe文件的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • python實(shí)現(xiàn)的簡單FTP上傳下載文件實(shí)例

    python實(shí)現(xiàn)的簡單FTP上傳下載文件實(shí)例

    這篇文章主要介紹了python實(shí)現(xiàn)的簡單FTP上傳下載文件的方法,實(shí)例分析了Python基于FTP模塊實(shí)現(xiàn)文件傳輸?shù)募记?需要的朋友可以參考下
    2015-06-06
  • python?配置uwsgi?啟動(dòng)Django框架的詳細(xì)教程

    python?配置uwsgi?啟動(dòng)Django框架的詳細(xì)教程

    這篇文章主要介紹了python?配置uwsgi?啟動(dòng)Django框架,本文給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12

最新評論