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

python黑魔法之編碼轉換

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

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

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

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

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

答案是,有!

python的編碼轉換流程實際上是兩段式轉換:

source -> unicode -> dest

首先將字符串從原始編碼轉換成unicode。再將unicode轉換成目標編碼。

第一步我們一般采用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 默認值。如果出現(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)是個很不經推敲的算法。
比如utf8和gbk在前兩個字節(jié)就有交集的部分。當一個utf8的字符串以gbk編碼decode的時候,出現(xiàn)錯誤是從第三個字節(jié)開始(前兩個字節(jié)也能夠在gbk編碼范圍中對應到一個漢字)。
如:

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

所以針對這種情況,做了下改進:

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)

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

相關文章

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

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

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

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

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

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

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

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

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

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

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

    5款最強且免費的Python IDE小結

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

    如何將python項目部署在一臺服務器上

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

    使用pyinstaller打包.exe文件的詳細教程

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

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

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

    python?配置uwsgi?啟動Django框架的詳細教程

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

最新評論