快速入手Python字符編碼
前言
對(duì)于很多接觸Python的人而言,字符的處理和語言整體的溫順可靠相比顯得格外桀驁不馴難以駕馭。
文章針對(duì)Python 2.7,主要因?yàn)?對(duì)的編碼已經(jīng)有了很大的改善并且實(shí)際原理一樣,更改一下操作命令即可。
了解完本文,你可以輕松解決文字處理,特殊平臺(tái)(Windows?)下的編碼,爬蟲編碼等問題。
閱讀建議
本文分為如下幾個(gè)部分:
1.原理
2.具體操作
3.建議的使用習(xí)慣
4.疑難問題解答
如果想要了解我給出的使用習(xí)慣,可以直接跳到建議的使用習(xí)慣。
如果只想要解決相關(guān)問題可以直接跳到疑難問題解答。
希望本文能夠幫到你。
原理
為了理解方便,這里不談理論只做類比,具體想要進(jìn)一步了解各種編碼的理論的百度一下好了。
首先說一下我們?yōu)槭裁磿?huì)碰到各式各樣的編碼問題:
1.因?yàn)槲覀儧]有統(tǒng)一編碼
2.因?yàn)槲覀儧]有用對(duì)命令(傳對(duì)數(shù)據(jù))
再說一下編碼是什么,Python的編碼看似復(fù)雜,實(shí)際上可以看做只有兩類編碼:Unicode,二進(jìn)制
1.Unicode 相信都很熟悉:,就是\u0000
這樣的
2.二進(jìn)制編碼也很簡(jiǎn)單,就是\x00\x00
這樣的,平??吹降?code>utf-8,cp936
都是二進(jìn)制編碼
3.二進(jìn)制編碼是具象的,10001100
原樣就可以存儲(chǔ),而Unicode是抽象的,不能這樣存
#coding=utf8 # Unicode編碼演示 print('Unicode:') print(repr(u'Unicode編碼'))` # 二進(jìn)制編碼演示 print(u'二進(jìn)制編碼:') print(repr('Unicode編碼'))` # 只是看個(gè)樣子,代碼不必去深究
再說怎么做,就是只有同種編碼之間才可以操作
舉個(gè)簡(jiǎn)單的類比
就把一串?dāng)?shù)據(jù)比為烤鴨,我們作為人和鴨子不同種看待烤鴨的態(tài)度完全不一樣。
我們看到的是晚上的配菜,鴨子看到的是自己二舅。
那么我在逛烤鴨店的時(shí)候用錯(cuò)編碼就會(huì)報(bào)錯(cuò)。
因?yàn)槲以诳绝喌昕吹搅藵M世界的二舅。
這里說的同種就是我們熟悉的各種編碼方式:utf-8,unicode,ucs-bom
這也就是編碼問題的核心,非常重要。
最后說一下Python的環(huán)境
1.本身代碼是用Ascii解碼的,文件里有Ascii無法解碼的內(nèi)容的話要告知Python怎么解碼
2.內(nèi)部大量命令都是默認(rèn)接受Unicode
# 告知的命令就是下面這一行,刪掉就會(huì)報(bào)錯(cuò) #coding=utf8 print(u'測(cè)試編碼')
具體操作
拿到各種編碼的內(nèi)容自然是不用說,那么如果我們想要自己構(gòu)造怎么做呢,看下面:
#coding=utf8 # 字符串前面加u會(huì)默認(rèn)構(gòu)造出Unicode的字符串 unicodeString = u'Unicode字符串' # 字符串前面什么都不加會(huì)構(gòu)造出默認(rèn)編碼(首行限定了現(xiàn)在的utf8)的字符串 utf8String = 'Utf-8字符串' # 當(dāng)然,沒有首行,默認(rèn)的編碼是Ascii
那么他們之間怎么轉(zhuǎn)換呢,同樣很簡(jiǎn)單:
# 接上一段程序 # Unicode轉(zhuǎn)化為二進(jìn)制編碼中的一種:utf8 unicodeString.encode('utf8') # 二進(jìn)制編碼根據(jù)自己的編碼種類轉(zhuǎn)化為Unicode utf8String.decode('utf8') # 如果二進(jìn)制編碼中混進(jìn)了奇怪的東西可以根據(jù)需求用特殊的decode策略 print(repr('u8字\x00符串'.decode('utf8', 'replace')))
那么怎么樣會(huì)出現(xiàn)問題呢:
# 接上一段程序 # 如果我們把他們轉(zhuǎn)化成同樣的編碼方式就可以操作(例如相加) print(repr(unicodeString + utf8String.decode('utf8'))) print(repr(unicodeString.encode('utf8') + utf8String)) # 但如果不轉(zhuǎn)化,當(dāng)然就會(huì)出現(xiàn)滿世界的烤鴨二舅啦 unicodeString + utf8String # 所以另一方面也發(fā)現(xiàn),編碼轉(zhuǎn)換是需要我們告訴程序怎么做的 # 所有`decode`操作都會(huì)生成Unicode編碼,這是為了方便我之前說的大量接受Unicode的內(nèi)部命令
所以我們需要確定程序使用的編碼,這是我們需要告訴程序的東西
1.一方面在操作字符串的時(shí)候確定是同種編碼
2.另一方面在使用非自己寫的命令時(shí),一般使用Unicode,或者使用接收二進(jìn)制編碼的命令
#coding=utf8 # 這里拿寫入文件舉例 # 一般使用Unicode with open('Unicode.txt', 'w') as f: f.write(u'Unicode測(cè)試') # 或者使用接收二進(jìn)制編碼的命令 with open('Utf8.txt', 'wb') as f: f.write('Utf8測(cè)試') # 你可以反過來做個(gè)測(cè)試,自然會(huì)報(bào)錯(cuò) # 二進(jìn)制的命令方便了在不知道怎么解碼的情況下也能進(jìn)行操作(寫入文件)
我建議的使用習(xí)慣
相信到這里我已經(jīng)把我對(duì)于編碼的理解講完了。
我們?yōu)槭裁磿?huì)碰到各式各樣的編碼問題:
1.因?yàn)槲覀儧]有統(tǒng)一編碼
2.因?yàn)槲覀儧]有用對(duì)命令(傳對(duì)數(shù)據(jù))
所以這里再重申一下八字真言:確定編碼,同類交互
1.碰到問題,問一下自己,我現(xiàn)在是哪種編碼
2.同一種編碼才能交互,那我應(yīng)該是哪種編碼
這里給出我的使用習(xí)慣:
1.確定一種內(nèi)部編碼
2.內(nèi)部編碼的選擇優(yōu)先級(jí)如下:程序必須使用的編碼、第三方包使用的編碼、你喜歡的編碼、Unicode
3.在輸出時(shí)再更改到特定的編碼
記得在開始整個(gè)程序之前確定內(nèi)部的編碼,否則編碼一團(tuán)糟會(huì)產(chǎn)生很多不必要的bug。
不要迷信內(nèi)部Unicode,例如Evernote開發(fā)就應(yīng)該根據(jù)第三方包使用的Utf8確定內(nèi)部編碼。
疑難問題解答
編碼識(shí)別
說了要確定編碼,那么拿到一串二進(jìn)制要怎么確定編碼呢?
最簡(jiǎn)單的方法是chardet:(需要安裝)
python -m pip install chardet
使用非常簡(jiǎn)單:
#coding=utf8 from chardet import detect print(detect('這是一串utf8的測(cè)試字符')) # 結(jié)果:`{'confidence': 0.99, 'encoding': 'utf-8'}`
另外例如抓取網(wǎng)站,那么頭文件中很有可能有提示如何解碼,記得不要忘記了。
編碼轉(zhuǎn)換
很可能因?yàn)樽址袇㈦s了奇怪的東西,導(dǎo)致即使編碼種類正確,依舊無法解碼。
我知道我之前講過了,但可能有人直接跳疑難問題解答嘛。
這里可以使用decode
的第二個(gè)參數(shù):
#coding=utf8 # 字符串中混進(jìn)了\x00 rubbishUtf8String = 'Utf-8字\x00符串' print(repr(rubbishUtf8String.decode('utf8', 'replace'))) print(repr(rubbishUtf8String.decode('utf8', 'ignore')))
特殊平臺(tái)下編碼
很多人都說Windows是個(gè)坑,即使在Python 3下面也一樣。
因?yàn)橹形奈募鰜矶际莵y碼。
這里使用一個(gè)取巧的方法:平臺(tái)編碼再特殊,起碼命令行讀取和創(chuàng)建一個(gè)文件夾不會(huì)出亂碼吧。
import sys, os for folder in os.walk('.').next()[1]: print(folder.decode(sys.stdin.encoding))
同樣的輸入輸出也可以這樣做優(yōu)化:
import sys def sys_print(msg): print(msg.encode(sys.stdin.encoding)) def sys_input(msg): return raw_input(msg.encode(sys.stdin.encoding)).decode(sys.stdin.encoding)
文件寫入
如果抓下來一個(gè)內(nèi)容不知道怎么解碼,但還是想要寫入文件怎么辦
寫入文件的時(shí)候制定用二進(jìn)制命令即可:
#coding=utf8 import urllib with open('Utf8.txt', 'wb') as f: f.write('Utf8測(cè)試') # 比如抓了個(gè)網(wǎng)頁,不知道編碼也可以寫入文件進(jìn)行一系列操作 content = urllib.urlopen('http://www.baidu.com').read() with open('baidu.txt', 'wb') as f: f.write(content)
裸Unicode字符
Unicode存成六個(gè)Ascii字符怎么辦?其實(shí)也可以decode
#coding=utf8 # 這是普通的Unicode s = u'測(cè)' for i in s: print(i) print(repr(s)) # 這是裸Unicode,實(shí)際存成了六個(gè)Ascii s = repr(s)[2:-1] for i in s: print(i) print(repr(s)) # 轉(zhuǎn)化其實(shí)也很簡(jiǎn)單 s = s.decode('unicode-escape') for i in s: print(i) print(repr(s))
總結(jié)
以上就是詳細(xì)介紹Python字符編碼的全部?jī)?nèi)容,希望讀完這篇文章能對(duì)大家能有幫助,有什么不足之處萬望指正,希望大家多多支持腳本之家。
相關(guān)文章
python格式化輸出%s與format()的用法對(duì)比
這篇文章主要為大家介紹了python格式化輸出%s與format()的用法對(duì)比,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-10-10python 解決數(shù)據(jù)庫寫入時(shí)float自動(dòng)變?yōu)檎麛?shù)的問題
這篇文章主要介紹了python 解決數(shù)據(jù)庫寫入時(shí)float自動(dòng)變?yōu)檎麛?shù)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07django rest framework vue 實(shí)現(xiàn)用戶登錄詳解
這篇文章主要介紹了django rest framework vue 實(shí)現(xiàn)用戶登錄詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-07-07python鏈接sqlite數(shù)據(jù)庫的詳細(xì)代碼實(shí)例
SQLite數(shù)據(jù)庫是一款非常小巧的嵌入式開源數(shù)據(jù)庫軟件,也就是說沒有獨(dú)立的維護(hù)進(jìn)程,所有的維護(hù)都來自于程序本身,它是遵守ACID的關(guān)聯(lián)式數(shù)據(jù)庫管理系統(tǒng),它的設(shè)計(jì)目標(biāo)是嵌入式的,而且目前已經(jīng)在很多嵌入式產(chǎn)品中使用了它,它占用資源非常的低2021-09-09Flask框架使用DBUtils模塊連接數(shù)據(jù)庫操作示例
這篇文章主要介紹了Flask框架使用DBUtils模塊連接數(shù)據(jù)庫操作,結(jié)合實(shí)例形式較為詳細(xì)的分析了flask框架使用DBUtils模塊連接數(shù)據(jù)庫的常見操作技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下2018-07-07