配置: Python 2.7 + Sublime Text 2 + OS X 10.10
本文意在理清各種編碼的關系並以此解決 Python 中的編碼問題。
1 編碼基本概念
只有先了解字符表、編碼字符集、字符編碼三者的基本概念,才能直入編碼問題的核心。
1.1 字符表 | Abstract Character Repertoire
字符表是一個系統支持的所有可讀或者可顯示的抽象字符的集合。也就是說字符表里面的元素是可顯示的字符。例如:“A”、“B”、“文”這樣的元素。
1.2 編碼字符集 | Coded Character set
編碼字符集是這樣的一個集合,集合中的元素是字符在字符表中的位置。例如元素 65 代表字符 “A” 在字符表中的位置。
計算機統一使用 Unicode 作為編碼字符集。
1.3 字符編碼 | Character Encoding Form
由於 Unicode 這個編碼字符集十分龐大,每個元素都需要用好幾個字節表示,為了節省存儲空間以及數據傳輸成本。人們使用字符編碼將 Unicode 表示的字符串轉換成字節序列。
將字節序列轉換成 Unicode 編碼的過程稱為解碼(decode);將 Unicode 編碼轉換成字節序列的過程稱為編碼(encode)。
記住字符編碼的目的是為了節省存儲空間以及數據傳輸成本。
常見的字符編碼有 ASCII、UTF-8、GBK等,應用最廣泛的字符編碼是 UTF-8 。
2 Python 的編碼字符集
Python 出現的時候 Unicode 的標准還沒制定好,所以 Python 2 只支持 ASCII 編碼字符集。ASCII 編碼字符集和 ASCII 字符編碼是同一個集合,也就是說 ASCII 碼是沒有進行轉換直接進行存儲的。
所以 Python 中的字符串默認只支持 ASCII 中的字符,為了支持 Unicode 字符,需要在包含 非 ASCII 碼字符的字符串前面添加 u
,像這樣:
u"中文"
3 Python 的字符編碼
Python 默認支持的字符編碼也是 ASCII,一般都不夠用,我們通常希望將其編碼為 UTF-8(UTF-8 without BOM),為了實現這一目標,需要在文件頭部進行字符編碼聲明,並將文件保存為 UTF-8 格式。
字符編碼聲明必須放在文件的前兩行,聲明方式如下:
# -*- coding:utf-8 -*-
或者,
#coding=utf-8
Python 對這類聲明的格式要求比較嚴格,所在位置錯誤或者中間多添加空格都會導致聲明失效。
-
如果未添加聲明,會出現類似這樣的錯誤
SyntaxError: Non-ASCII character '\xe4' in file .../sample.py on line 4, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
-
如果添加了 UTF-8 的聲明,但是文件保存為 GBK 格式,會出現錯誤
[Decode error - output not utf-8]
。
3.1 Sublime Text 2 編譯錯誤
在 ST2 中,即使進行了正確的設置,依然會出現錯誤 UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
。這是由於 ST2 在輸出字符串時無法識別 Python 對標准輸入輸出的編碼,而默認使用了 ASCII 編碼,解決方案是這樣的,通過 Sublime Text 2 -> Preference -> Browse Packages
找到 Python 文件夾,打開 Python.sublime-build
文件,添加一個 env 域:
"env": {"PYTHONIOENCODING": "utf8"},
另一個解決方案是在 .py
文件中對字符串進行顯式的編碼,例如:
print u"中文".encode("utf-8")
關於該問題的詳細描述參見 有關 Python 2 和 Sublime Text 中文 Unicode 編碼問題的分析與理解 。
4 附錄
最后添加一個例子以方便理解。
文件 Python.sublime-build
:
{
"cmd": ["python2.7", "-u", "$file"],
"path":"/System/Library/Frameworks/Python.framework/Versions/2.7/bin/",
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"env": {"PYTHONIOENCODING": "utf8"},
"selector": "source.python"
}
文件 sample.py
:
#! /usr/bin/env python
#coding=utf-8
print u"你好,"
print u"我是唐衣可俊!".encode('utf-8')
輸出:
你好,
我是唐衣可俊!
參考鏈接
十分鍾搞清字符集和字符編碼(對字符集和字符編碼進行了比較系統詳盡的介紹)
有關 Python 2 和 Sublime Text 中文 Unicode 編碼問題的分析與理解(關於 ST2 對 Unicode 字符輸出報錯的問題進行了詳細的分析)