用python处理中文,读取文件或消息时,如果发现乱码(字符串处理,读写文件,print),大多数人的做法是,调用encode/decode进行调试,并没有明确思考为何出现乱码, 今天我们来讨论一下如何处理编码问题。
注意: 以下讨论为Python2.x版本, Py3k下未测试
调试时最常出现的错误
错误1
Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: ‘ascii‘ codec can‘t decode byte 0xe6 in position 0: ordinal
错误2
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/System/Library/Frameworks/Python.framework/Versions/2.7/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 characters in position 0-1: ordinal not in range(128)
首先
必须有大体概念,了解下字符集,字符编码
ASCII | Unicode | UTF-8 | 等等
字符编码笔记:ASCII,Unicode和UTF-8
str 和 unicode
str和unicode都是basestring的子类
所以有判断是否是字符串的方法
def is_str(s): return isinstance(s, basestring)
str和unicode 转换
str -> decode(‘the_coding_of_str‘) -> unicode unicode -> encode(‘the_coding_you_want‘) -> str
区别
str是字节串,由unicode经过编码(encode)后的字节组成的
声明方式
>>> s = ‘中文‘ s = u‘中文‘.encode(‘utf-8‘) >>> type(‘中文‘) <type ‘str‘>
求长度(返回字节数)
>>> u‘中文‘.encode(‘utf-8‘) ‘\xe4\xb8\xad\xe6\x96\x87‘ >>> len(u‘中文‘.encode(‘utf-8‘)) 6
unicode才是真正意义上的字符串,由字符组成
声明方式
>>> s = u‘中文‘ >>> s = ‘中文‘.decode(‘utf-8‘) >>> s = unicode(‘中文‘, ‘utf-8‘) >>> type(u‘中文‘) <type ‘unicode‘>
求长度(返回字符数),在逻辑中真正想要用的
>>> u‘中文‘ u‘\u4e2d\u6587‘ >>> len(u‘中文‘) 2
结论
搞明白要处理的是str还是unicode, 使用对的处理方法(str.decode/unicode.encode)
下面是判断是否为unicode/str的方法
>>> isinstance(u‘中文‘, unicode) True >>> isinstance(‘中文‘, unicode) False >>> isinstance(‘中文‘, str) True >>> isinstance(u‘中文‘, str) False
简单原则:不要对str使用encode,不要对unicode使用decode (事实上可以对str进行encode的,具体见最后,为了保证简单,不建议)
>>> ‘中文‘.encode(‘utf-8‘) Traceback (most recent call last): File "", line 1, in UnicodeDecodeError: ‘ascii‘ codec can‘t decode byte 0xe4 in position 0: ordinal not in range(128) >>> u‘中文‘.decode(‘utf-8‘) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/System/Library/Frameworks/Python.framework/Versions/2.7/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 characters in position 0-1: ordinal not in range(128)
不同编码转换,使用unicode作为中间编码
#s是code_A的str s.decode(‘code_A‘).encode(‘code_B‘)
文件处理,IDE和控制台
处理流程,可以这么使用,把python看做一个水池,一个入口,一个出口
入口处,全部转成unicode, 池里全部使用unicode处理,出口处,再转成目标编码(当然,有例外,处理逻辑中要用到具体编码的情况)
读文件 外部输入编码,decode转成unicode 处理(内部编码,统一unicode) encode转成需要的目标编码 写到目标输出(文件或控制台)
IDE和控制台报错,原因是print时,编码和IDE自身编码不一致导致
输出时将编码转换成一致的就可以正常输出
>>> print u‘中文‘.encode(‘gbk‘) ???? >>> print u‘中文‘.encode(‘utf-8‘) 中文
建议
规范编码
统一编码,防止由于某个环节产生的乱码
环境编码,IDE/文本编辑器, 文件编码,数据库数据表编码
保证代码源文件编码
这个很重要
py文件默认编码是ASCII, 在源代码文件中,如果用到非ASCII字符,需要在文件头部进行编码声明 文档
不声明的话,输入非ASCII会遇到的错误,必须放在文件第一行或第二行
File "XXX.py", line 3 SyntaxError: Non-ASCII character ‘\xd6‘ in file c.py on line 3, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details声明方法
# -*- coding: utf-8 -*- 或者 #coding=utf-8
若头部声明coding=utf-8, a = ‘中文‘ 其编码为utf-8
若头部声明coding=gb2312, a = ‘中文‘ 其编码为gbk
so, 同一项目中所有源文件头部统一一个编码,并且声明的编码要和源文件保存的编码一致(编辑器相关)
在源代码用作处理的硬编码字符串,统一用unicode
将其类型和源文件本身的编码隔离开, 独立无依赖方便流程中各个位置处理
if s == u‘中文‘: #而不是 s == ‘中文‘ pass #注意这里 s到这里时,确保转为unicode
以上几步搞定后,你只需要关注两个 unicode和 你设定的编码(一般使用utf-8)
处理顺序
1. Decode early 2. Unicode everywhere 3. Encode later
相关模块及一些方法
获得和设置系统默认编码
>>> import sys >>> sys.getdefaultencoding() ‘ascii‘ >>> reload(sys) <module ‘sys‘ (built-in)> >>> sys.setdefaultencoding(‘utf-8‘) >>> sys.getdefaultencoding() ‘utf-8‘ >>> str.encode(‘other_coding‘)
在python中,直接将某种编码的str进行encode成另一种编码str
#str_A为utf-8 str_A.encode(‘gbk‘) 执行的操作是 str_A.decode(‘sys_codec‘).encode(‘gbk‘) 这里sys_codec即为上一步 sys.getdefaultencoding() 的编码
‘获得和设置系统默认编码‘和这里的str.encode是相关的,但我一般很少这么用,主要是觉得复杂不可控,还是输入明确decode,输出明确encode来得简单些
chardet
文件编码检测,下载
>>> import chardet >>> f = open(‘test.txt‘,‘r‘) >>> result = chardet.detect(f.read()) >>> result {‘confidence‘: 0.99, ‘encoding‘: ‘utf-8‘}
\u字符串转对应unicode字符串
>>> u‘中‘ u‘\u4e2d‘ >>> s = ‘\u4e2d‘ >>> print s.decode(‘unicode_escape‘) 中 >>> a = ‘\\u4fee\\u6539\\u8282\\u70b9\\u72b6\\u6001\\u6210\\u529f‘ >>> a.decode(‘unicode_escape‘) u‘\u4fee\u6539\u8282\u70b9\u72b6\u6001\u6210\u529f‘

本教程演示如何使用Python處理Zipf定律這一統計概念,並展示Python在處理該定律時讀取和排序大型文本文件的效率。 您可能想知道Zipf分佈這個術語是什麼意思。要理解這個術語,我們首先需要定義Zipf定律。別擔心,我會盡量簡化說明。 Zipf定律 Zipf定律簡單來說就是:在一個大型自然語言語料庫中,最頻繁出現的詞的出現頻率大約是第二頻繁詞的兩倍,是第三頻繁詞的三倍,是第四頻繁詞的四倍,以此類推。 讓我們來看一個例子。如果您查看美國英語的Brown語料庫,您會注意到最頻繁出現的詞是“th

Python 提供多種從互聯網下載文件的方法,可以使用 urllib 包或 requests 庫通過 HTTP 進行下載。本教程將介紹如何使用這些庫通過 Python 從 URL 下載文件。 requests 庫 requests 是 Python 中最流行的庫之一。它允許發送 HTTP/1.1 請求,無需手動將查詢字符串添加到 URL 或對 POST 數據進行表單編碼。 requests 庫可以執行許多功能,包括: 添加表單數據 添加多部分文件 訪問 Python 的響應數據 發出請求 首

本文解釋瞭如何使用美麗的湯庫來解析html。 它詳細介紹了常見方法,例如find(),find_all(),select()和get_text(),以用於數據提取,處理不同的HTML結構和錯誤以及替代方案(SEL)

處理嘈雜的圖像是一個常見的問題,尤其是手機或低分辨率攝像頭照片。 本教程使用OpenCV探索Python中的圖像過濾技術來解決此問題。 圖像過濾:功能強大的工具圖像過濾器

PDF 文件因其跨平台兼容性而廣受歡迎,內容和佈局在不同操作系統、閱讀設備和軟件上保持一致。然而,與 Python 處理純文本文件不同,PDF 文件是二進製文件,結構更複雜,包含字體、顏色和圖像等元素。 幸運的是,借助 Python 的外部模塊,處理 PDF 文件並非難事。本文將使用 PyPDF2 模塊演示如何打開 PDF 文件、打印頁面和提取文本。關於 PDF 文件的創建和編輯,請參考我的另一篇教程。 準備工作 核心在於使用外部模塊 PyPDF2。首先,使用 pip 安裝它: pip 是 P

本教程演示瞭如何利用Redis緩存以提高Python應用程序的性能,特別是在Django框架內。 我們將介紹REDIS安裝,Django配置和性能比較,以突出顯示BENE

自然語言處理(NLP)是人類語言的自動或半自動處理。 NLP與語言學密切相關,並與認知科學,心理學,生理學和數學的研究有聯繫。在計算機科學

本文比較了Tensorflow和Pytorch的深度學習。 它詳細介紹了所涉及的步驟:數據準備,模型構建,培訓,評估和部署。 框架之間的關鍵差異,特別是關於計算刻度的


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

Atom編輯器mac版下載
最受歡迎的的開源編輯器

Dreamweaver Mac版
視覺化網頁開發工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。