更多精彩內(nèi)容薪捍,請關(guān)注微信公眾號:后端技術(shù)小屋
大家可能和我一樣,在Python日常開發(fā)過程中會遇到各種各樣的編碼問題配喳。因此在此以個(gè)人的踩坑經(jīng)驗(yàn)總結(jié)出一些常見問題和解決方案酪穿。
0 如何查看py源文件編碼
vim py文件
輸入
:set fileencoding
輸出
fileencoding=utf-8
1 如何確定py中靜態(tài)字符串的編碼
靜態(tài)字符串的編碼方式取決于文件頭中coding
的設(shè)置。在下面的代碼中晴裹,變量name
以UTF-8編碼被济。
#!/usr/bin/env python
# coding: utf-8
name = "后端技術(shù)小屋"
如果不設(shè)置coding
,運(yùn)行py文件時(shí)便會報(bào)語法錯(cuò)誤涧团,因?yàn)镻ython Interpreter不識別文件中的中文字符
SyntaxError: Non-ASCII character '\xe5' in file 1.py on line 2, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
2 如何查看標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出的編碼
以下三種方法皆可查看stdin/stdout的編碼
2.1 通過Python sys庫查看
$ python
Python 2.7.6 (default, Nov 13 2018, 12:45:42)
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> print sys.stdin.encoding
UTF-8
>>> print sys.stdout.encoding
UTF-8
>>>
2.2 查看環(huán)境變量LANG
$ echo $LANG
en_US.UTF-8
2.3 執(zhí)行l(wèi)ocale
$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US:
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
3 如何修改標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出的編碼
首先我們需要知道是環(huán)境變量LANG
決定了stdin
和stdout
的編碼
如果只是想臨時(shí)修改只磷,在命令行通過export LANG='XXX'
指定標(biāo)準(zhǔn)輸入/輸出編碼即可。當(dāng)終端退出時(shí)該設(shè)置即失效少欺。
如果想永久修改: 執(zhí)行vim /etc/sysconfig/i18n
, 在其中修改LANG的取值喳瓣,然后執(zhí)行source /etc/sysconfig/i18n
即可生效。
4 定義字符串時(shí)前綴'u'和'b'的區(qū)別
首先我們假設(shè)py文件頭中# coding: utf-8
執(zhí)行a = u'后端技術(shù)小屋'
時(shí)赞别,會將UTF-8編碼的靜態(tài)字符串轉(zhuǎn)化成Unicode編碼畏陕,最后賦值給a;
執(zhí)行b = b'后端技術(shù)小屋'
時(shí)仿滔,則直接將UTF-8編碼的靜態(tài)字符串賦值給b
5 定義a=u'后端技術(shù)小屋'和b=b'后端技術(shù)小屋'惠毁,打印a和b的結(jié)果為何相同
假設(shè)py文件頭中指定coding
為UTF-8,且標(biāo)準(zhǔn)輸入/輸出的編碼為UTF-8
Python執(zhí)行print a
時(shí)崎页,會自動將Unicode轉(zhuǎn)化成標(biāo)準(zhǔn)輸出的編碼格式UTF-8鞠绰,然后輸出
Python執(zhí)行print b
時(shí),字符串b
的編碼為UTF-8飒焦,恰好與標(biāo)準(zhǔn)輸出相同蜈膨。雖然定義a和b時(shí)的編碼方式不同,但是打印它們時(shí)都會轉(zhuǎn)化為標(biāo)準(zhǔn)輸出的編碼牺荠,所以我們看到打印a和b的結(jié)果相同翁巍。
實(shí)際上這里有一些巧合:字符串b
的編碼恰好與標(biāo)準(zhǔn)輸出相同。一旦b的編碼和標(biāo)準(zhǔn)輸出的編碼不一致了(比如b的編碼換成了GBK)休雌,我們看到的將是亂碼灶壶,因?yàn)镚BK編碼無法自動轉(zhuǎn)化為UTF-8,而我們在Python開發(fā)中遇到的中文亂碼問題大部分來源于此杈曲。
在實(shí)際開發(fā)中驰凛,強(qiáng)烈建議將可能含有中文的字符串一律轉(zhuǎn)換成Unicode編碼之后再打印胸懈。如下所示:
# coding: gbk
a = "后端開發(fā)小屋" # GBK編碼
aa = a.decode("gbk") # Unicode編碼
print aa
# coding: utf-8
a = "后端開發(fā)小屋" # UTF-8編碼
aa = a.decode("utf-8") # Unicode編碼
print aa
6 執(zhí)行py的標(biāo)準(zhǔn)輸出重定向到文件中是什么編碼?
編碼方式同標(biāo)準(zhǔn)輸出
7 為何vim打開文件無亂碼恰响,但是cat文件有亂碼
說明文件和標(biāo)準(zhǔn)輸出編碼不一致趣钱。而vim支持文件編碼,所以vim打開文件無亂碼渔隶,cat文件有亂碼羔挡。所以解決思路是使得文件編碼與標(biāo)準(zhǔn)輸出編碼一致,即可消除亂碼间唉。
解決方法1: 通過iconv -f XXX -t XXX file, 將文件轉(zhuǎn)碼绞灼,使得其編碼與標(biāo)準(zhǔn)輸出一致
解決方法2: 修改標(biāo)準(zhǔn)輸出編碼(參考問題2), 使得其與文件編碼一致
8 vim打開文件有亂碼,但是cat文件無亂碼
說明vim不識別此種文件編碼
解決方法:
- vim中輸入
:set fileencoding
, 查看文件編碼 - vim ~/.vimrc, 在set fileencodings列表中加入該文件編碼呈野,例如
set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1
- vim重新打開文件
9 總結(jié)
說了這么多低矮,總結(jié)下:
- Python開發(fā)中,對于可能含有中文的字符串被冒,如需打印军掂,需將其轉(zhuǎn)化為Unicode編碼。因?yàn)閜ython會自動將unicode轉(zhuǎn)化成輸出介質(zhì)的編碼昨悼。
- 標(biāo)準(zhǔn)輸出蝗锥、標(biāo)準(zhǔn)輸入、文件率触、vim(或其他編輯器)上的亂碼問題终议,可根據(jù)如上問題舉一反三,對癥下藥加以解決葱蝗。
推薦閱讀
- STL源碼分析--vector
- STL源碼分析--hashtable
- STL源碼分析--algorithm
- zookeeper client原理總結(jié)
- redis實(shí)現(xiàn)分布式鎖
- 推薦幾個(gè)好用的效率神器
- C/C++關(guān)鍵字之restrict
- 現(xiàn)代C++之右值語義
更多精彩內(nèi)容穴张,請掃碼關(guān)注微信公眾號:后端技術(shù)小屋。如果覺得文章對你有幫助的話两曼,請多多分享皂甘、轉(zhuǎn)發(fā)、在看悼凑。