更多精彩內容,請關注微信公眾號:后端技術小屋
大家可能和我一樣,在Python日常開發程序中會遇到各種各樣的編碼問題,因此在此以個人的踩坑經驗總結出一些常見問題和解決方案,
0 如何查看py源檔案編碼
vim py檔案
輸入
:set fileencoding
輸出
fileencoding=utf-8
1 如何確定py中靜態字串的編碼
靜態字串的編碼方式取決于檔案頭中coding的設定,在下面的代碼中,變數name以UTF-8編碼,
#!/usr/bin/env python
# coding: utf-8
name = "后端技術小屋"
如果不設定coding,運行py檔案時便會報語法錯誤,因為Python 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 如何查看標準輸入和標準輸出的編碼
以下三種方法皆可查看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 查看環境變數LANG
$ echo $LANG
en_US.UTF-8
2.3 執行locale
$ 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 如何修改標準輸入和標準輸出的編碼
首先我們需要知道是環境變數LANG決定了stdin和stdout的編碼
如果只是想臨時修改,在命令列通過export LANG='XXX'指定標準輸入/輸出編碼即可,當終端退出時該設定即失效,
如果想永久修改: 執行vim /etc/sysconfig/i18n, 在其中修改LANG的取值,然后執行source /etc/sysconfig/i18n即可生效,
4 定義字串時前綴'u'和'b'的區別
首先我們假設py檔案頭中# coding: utf-8
執行a = u'后端技術小屋'時,會將UTF-8編碼的靜態字串轉化成Unicode編碼,最后賦值給a;
執行b = b'后端技術小屋'時,則直接將UTF-8編碼的靜態字串賦值給b
5 定義a=u'后端技術小屋'和b=b'后端技術小屋',列印a和b的結果為何相同
假設py檔案頭中指定coding為UTF-8,且標準輸入/輸出的編碼為UTF-8
Python執行print a時,會自動將Unicode轉化成標準輸出的編碼格式UTF-8,然后輸出
Python執行print b時,字串b的編碼為UTF-8,恰好與標準輸出相同,雖然定義a和b時的編碼方式不同,但是列印它們時都會轉化為標準輸出的編碼,所以我們看到列印a和b的結果相同,
實際上這里有一些巧合:字串b的編碼恰好與標準輸出相同,一旦b的編碼和標準輸出的編碼不一致了(比如b的編碼換成了GBK),我們看到的將是亂碼,因為GBK編碼無法自動轉化為UTF-8,而我們在Python開發中遇到的中文亂碼問題大部分來源于此,
在實際開發中,強烈建議將可能含有中文的字串一律轉換成Unicode編碼之后再列印,如下所示:
# coding: gbk
a = "后端開發小屋" # GBK編碼
aa = a.decode("gbk") # Unicode編碼
print aa
# coding: utf-8
a = "后端開發小屋" # UTF-8編碼
aa = a.decode("utf-8") # Unicode編碼
print aa
6 執行py的標準輸出重定向到檔案中是什么編碼?
編碼方式同標準輸出
7 為何vim打開檔案無亂碼,但是cat檔案有亂碼
說明檔案和標準輸出編碼不一致,而vim支持檔案編碼,所以vim打開檔案無亂碼,cat檔案有亂碼,所以解決思路是使得檔案編碼與標準輸出編碼一致,即可消除亂碼,
解決方法1: 通過iconv -f XXX -t XXX file, 將檔案轉碼,使得其編碼與標準輸出一致
解決方法2: 修改標準輸出編碼(參考問題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 總結
說了這么多,總結下:
- Python開發中,對于可能含有中文的字串,如需列印,需將其轉化為Unicode編碼,因為python會自動將unicode轉化成輸出介質的編碼,
- 標準輸出、標準輸入、檔案、vim(或其他編輯器)上的亂碼問題,可根據如上問題舉一反三,對癥下藥加以解決,
推薦閱讀
- STL原始碼分析--vector
- STL原始碼分析--hashtable
- STL原始碼分析--algorithm
- zookeeper client原理總結
- redis實作分布式鎖
- 推薦幾個好用的效率神器
- C/C++關鍵字之restrict
- 現代C++之右值語意
更多精彩內容,請掃碼關注微信公眾號:后端技術小屋,如果覺得文章對你有幫助的話,請多多分享、轉發、在看,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/264068.html
標籤:Python

