python unicode和string byte, unicode轉中文及轉換默認編碼


python unicode 和string那📺

開發過程中總是會碰到string, unicode, ASCII, 中文字符等編碼的問題, 每次碰到都要現搜, 很是浪費時間, 於是這次狠下心, 一定要搞清楚python 的string和Unicode到底怎么回事.

基礎知識

我們都知道計算機只認0和1, 要想在計算機顯示26個字母, 就要給他們一套映射規則: 計算機能認得的符號 --> 人類可讀的符號. 這轉換的過程就是一套編碼規則.

  • 字符集: 就是一套字符的集合(比如中文4000個漢字集合)
  • 字符編碼: 一套法則, 能夠將0/1和人類的語言之間進行轉換的法則

最初字符集比較少, ASCII 碼就夠用了(一些控制符和26個字母), 隨着計算機的發展, 各國語言都有自己獨特的編碼, 漢字的編碼也不斷地擴展, 從GBK到 GB18030/DBCS. 這個時候Unicode應運而生.

Unicode就是為了統一各國各地區的編碼規則, 重新搞了一套包羅地球上所有文化, 符號的字符集! Unicode沒有編碼規則, 只是一套包含全世界符號的字符集. Unicode也不完美, 於是后續有了眾多UTF編碼(UTF-8, UTF-16).

總之搞清楚一件事情, 一個字符用了UTF-8編碼的, 就要用UTF-8去解碼, 不然就會出現亂碼.


文本處理

在python-2.x, 處理文本時, 有string和unicode兩種類型

  • str類型就是一串bytes, 這種類型跟C語言中處理string是非常相似的
  • unicode就是一串unicode的數字映射(code point), 用於映射某個字符與一個unicode的對應關系.

看看代碼出來是如何的:

>>> a = "簡書" >>> type(a) <type 'str'> >>> a '\xe7\xae\x80\xe4\xb9\xa6' >>> print a 簡書 >>> u = u"簡書" >>> type(u) <type 'unicode'> >>> u u'\u7b80\u4e66' >>> print u 簡書 

從上面的代碼可以看到, a = "簡書"是string類型, 可以看到a是一串 '\xe7\xae\x80\xe4\xb9\xa6' byte字符, 而u = u"簡書"是一串\uxxxx的unicode數字, 通過print a 和 print u可以顯示出中文字符.

常見問題#1

大家經常犯的一個錯誤就是混淆了unicode以及通過unicode編碼存儲在string里面的類型.
比如上面的例子中 u'\u7b80' 是unicode, '\xe7\xae\x80'是byte string, byte和unicode之間一一對應, 可以相互轉換, 轉換規則如下:

>>> '\xe7\xae\x80'.decode('utf-8') u'\u7b80' >>> print '\xe7\xae\x80'.decode('utf-8') 簡 >>> u'\u7b80'.encode('utf-8') '\xe7\xae\x80' >>> print u'\u7b80'.encode('utf-8') 簡 

總結一下, 上面例子中

  • unicode和byte都指
  • byte string 里面存儲的是unicode通過utf-8編碼后得到的bytes
  • 所以byte string解碼(decode)后即可得到unicode
  • unicode是byte string通過utf-8解碼后得到的
  • unicode用utf-8編碼(encode)可以得到對應的bytes
Note: 總而言之 Unicode ------編碼------> byte string Unicode <-----解碼------- byte string 

Unicode就像是加密傳輸中的明文, 可以用UTF-8, UTF-16, UTF-7, UTF-32等對unicode進行加密, 最后解密還是要用回原本的加密方式來解密, 不然就解出亂碼啦.

常見問題#2

對unicode或者byte string編碼解碼方向搞錯

>>> u'\u7b80'.decode('utf-8') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/serena/Documents/data-pipeline/data-ci-sqlbuffet-env/lib/python2.7/encodings/utf_8.py", line 16, in decode return codecs.utf_8_decode(input, errors, True) UnicodeEncodeError: 'ascii' codec can't encode character u'\u7b80' in position 0: ordinal not in range(128) >>> '\xe7\xae\x80'.encode('utf-8') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 0: ordinal not in range(128) 

unicode應該是進行編碼的, 如果進行decode, 是會出現UnicodeEncodeError 異常的. bytes string同理, 應該進行解碼, 如果硬要進行編碼的話, 則拋出UnicodeDecodeError

常見問題#3

API調用不一致的問題. 在調用別人的API的時候, 需要看清楚是傳unicode還是byte string作為參數. 因為第三方的API有的是支持unicode, 有的是byte string, 甚至有的兩種類型都支持. 這個時候要清楚自己傳進去的參數是什么, 比如一些變量值是從http requests里面拉過來的, 這個時候你獲得的變量值很有可能是unicode類型(python requests get/post把返回值都轉成了unicode), 而如果第三方的API需要byte string, name就需要自己判斷一下並進行轉換. 否則就會出現各種奇怪的UnicodeError

雖然python 社區規定了在所有的API中使用unicode, 但是少數一部分的API處於安全考慮還是要求使用byte string. 需要注意一下.

常見問題#4

輸出類型不一致.
既然python社區推動到處使用unicode, 那么我們只要在開發過程中全部都轉成unicode是不是就萬事大吉了? 並不是, 當你要輸出文本到terminal或者到文件, 這個文本必須是byte string類型的.
如果不是的話, python會隱式地幫你將unicode轉成string, python默認采用ascii編碼,而中文編碼不在ascii編碼能夠表示的范圍之內,所以string無法將“你好”作為ascii編碼保存為str類型。

>>> string = unicode('你好', 'utf8') >>> print string 你好 >>> log = open('/var/tmp/debug.log', 'w') >>> log.write(string) 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) 

所以當你需要輸出的時候, 需要將你的unicode轉換成byte string再寫文件, 如果有中文的話, 要用'utf-8'或'GBK'等支持中文的編碼.

>>> string.encode('utf-8') 

python 2.x的unicode & str其實搞清楚之后來來回回就是那些小問題, 希望對大家有幫助.

 

================================================================================================================================================

一、

在爬蟲抓取網頁信息時常需要將類似"\u4eba\u751f\u82e6\u77ed\uff0cpy\u662f\u5cb8"轉換為中文,實際上這是unicode的中文編碼。可用以下方法轉換:

1、

1 >>> s = u'\u4eba\u751f\u82e6\u77ed\uff0cpy\u662f\u5cb8'
2 >>> print s
3 人生苦短,py是岸
2、

1 >>> s = r'\u4eba\u751f\u82e6\u77ed\uff0cpy\u662f\u5cb8'
2 >>> s = s.decode('unicode_escape')
3 >>> print s
4 人生苦短,py是岸

二、

另外,在python2的字符編碼問題時常會遇到“UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)”的編碼錯誤。

而用以下方法通常可以解決:

1 import sys
2 reload(sys)
3 sys.setdefaultencoding('utf-8')
  此方法是將Python2的默認編碼ASCII改為 utf-8。但此方法不是一勞永逸的,可能會使一些代碼的行為變得怪異。





免責聲明!

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



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