python安全编码问题_浅谈Python中的编码问题
對于Python的初學者來說,編碼問題相當令人頭疼。本文就根據我在學習過程中遇到的問題簡單談一下Python中的編碼。首先簡單介紹一下幾種常見的編碼。
一、幾種常見的字符編碼
ASCII碼
ASCII碼是基于拉丁字碼的一套電腦編碼系統。它對英語字符與二進制位之間的關系做了統一的規定,使用指定的7位或8為二進制數組合來表示128或256種可能的字符。標準ASCII碼也叫基礎ASCII碼,使用7位二進制來表示所有的大寫和小寫字母,數字0到9、標點符號,以及在美式英語中使用的特殊控制字符。
英語中英文字母用128個符號編碼就夠了,但是用來表示其他語言,128個符號顯然是不夠的。比如,在法語中,字母上方有注音符號,它就無法用ASCII碼表示。至于亞洲國家的文字,使用的符號就更多了,漢字就多達10萬左右。
Unicode
Unicode(統一碼、萬國碼、單一碼)是一種在計算機上使用的字符編碼。Unicode 是為了解決傳統的字符編碼方案的局限而產生的,它為每種語言中的每個字符設定了統一并且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。
UTF-8
UTF-8(8位元Universal Character Set/Unicode Transformation Format)是一種針對Unicode的可變長度字符編碼。UTF-8最大的一個特點,是它是一種變長的編碼方式。它可以用來表示Unicode標準中的任何字符,且其編碼中的第一個字節與ASCII相容。UTF-8是在互聯網上使用最廣的一種Unicode的實現方式。
二、Python中的字符串類型
Python中的字符串有兩種類型:str類型和unicode類型。以字符串“中文”賦值給變量為例:
s='中文'
>>>type(s)
或者
s=u’中文’
>>>type(s)
在Python中,為了統一不同編碼的字符串的表示,同時簡化字符串的處理,其內部提供了一種統一化的文本類型unicode,即第二種形式的字符串。unicode類型的字符串只處理文本,并把文本以unicode形式在內部存儲。unicode類型的作用只用于代碼內部字符串的處理,而不關心外部文本的具體格式,可以看作是文本的抽象表示。前者定義了一個字符串,后者定義了一個unicode編碼的字符串。
但是實際上外界文本的不同編碼格式眾多。比如向一個網站提交數據,其有可能要求utf-8的編碼或者gbk的編碼,不同的編碼類型的內容是不同的, 這就需要將程序內部字符串轉換成可以與外界交互的編碼(如:utf-8,ascii,gdb等)。Python默認使用str類型來操作。嚴格來講,str并不一定是文本,它也有可能是二進制的內容,它提供的其實是字節的組合(unicode類型提供的是unicode字符集的組合),只是如果str中剛好是某種形式編碼的文本,它便可以當做文本處理(print等)。
三、python中常遇到的編碼問題
以下問題只有在Python2.x版本中出現,因為3.X版本中python環境就只有unicode類型的字符串了,即所有程序中處理的都會自動轉換成unicode字符串。
代碼文件編碼聲明
編寫Python腳本時,教程都會讓我們把“# -- coding: utf-8 --”加在代碼文件的第一行。這句話是告訴python這個文件里的文本用utf-8編碼。Python默認將代碼文件內容當做ASCII編碼處理,因此當文件中存在中文時就會拋出異常。加上這句編碼聲明后,Python就會依照utf-8的編碼形式解讀其中的字符,然會轉換成unicode編碼內部處理使用。注意這句編碼聲明一定要放在第一行或者第二行才生效,我之前就將它放在了其他位置,結果將源代碼文件從windows移動到Linux后,出現了編碼問題,文件中的中文注釋全成了亂碼。因為Windows中默認編碼為gbk,Linux默認編碼為utf-8。
或者也可以使用下面的語句來設置編碼方式:
import sys
reload(sys)
sys.setdefaultencoding('UTF-8')
編碼轉換
編寫python過程中經常遇到報錯“UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 0-1: ordinal not in range(128)”,為什么會出這樣的報錯呢?
第二節提到,字符串在Python內部使用unicode編碼,因此,在做編碼轉換時,通常需要以unicode作為中間編碼,即先將其他編碼的字符串解碼(decode)成unicode,再從unicode編碼(encode)成另一種編碼。
decode的作用是將普通字符串按照參數中的編碼格式進行解析,然后生成對應的unicode對象。如str1.decode(‘gb2312’),表示將字符串str1按照gb2312編碼解析為unicode對象。
encode的作用正好相反,是將一個unicode對象轉換為參數中指定的編碼格式的普通字符。如str2.encode(‘gb2312′),表示將unicode對象str2轉換成gb2312編碼的字符串。
因此,轉碼的時候一定要先搞明白,字符串str是什么編碼,然后decode成unicode,然后再encode成其他編碼。
代碼中字符串的默認編碼與代碼文件本身的編碼一致。也就是說,在utf8的文件中,字符串就是utf8編碼,如果是在gb2312的文件中,則其編碼為gb2312。通常,在沒有指定特定的編碼方式時,都是使用的系統默認編碼創建的代碼文件。
如果字符串是這樣定義:s=u’中文’
則該字符串就被定義為unicode對象了,即python的內部編碼,而與代碼文件本身的編碼無關。因此,對于這種情況做編碼轉換,只需要直接使用encode方法將其轉換成指定編碼即可。
如果一個字符串已經是unicode了,再進行解碼則將出錯,因此通常要對其編碼方式是否為unicode進行判斷:
isinstance(s, unicode) #用來判斷s是否為unicode
同樣,用非unicode編碼形式的str來encode會報錯 。
因此,程序會提示:UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 0-1: ordinal not in range(128),是因為Python調用了ASCII編碼解碼程序去處理unicode對象,導致拋出異常(ordinal not in range(128))。解決辦法則是用上一小節提到的第二種設置編碼的方式來修改默認的編碼模式即可。
輸出打印
我們在windows控制臺下打印中文時,經常出現屏幕上打印出的字和我們想要的結果不一致的情況。這是由于python編碼與控制臺編碼不一致造成的。Windows下控制臺中的編碼默認使用的是gbk,而在代碼中使用的是utf-8,python按照utf-8編碼打印到gbk編碼的控制臺下自然就不能打印出正確的漢字。
解決辦法一個是將源代碼的編碼方式改成gbk,也就是將源代碼文件的第一行改成:
# -*- coding: gbk -*-
另一種方式是保持源代碼文件的utf-8編碼方式不變,而是在聲明帶中文的變量前u,如:s1=u’中文’,這樣就可以正確打印中文了。
這里的u表示將后面跟的字符串以unicode格式存儲。python會根據代碼第一行聲明的utf-8編碼識別代碼中的漢字,然后轉換成unicode對象以unicode格式存在于內存中,而如果不加u,表明這僅僅是一個使用某種編碼的字符串,編碼格式取決于python對源碼文件編碼的識別,這里就是utf-8。Python在向控制臺輸出unicode對象的時候會自動根據輸出環境的編碼進行轉換,但如果輸出的不是unicode對象而是普通字符串,則會直接按照字符串的編碼輸出字符串,從而出現上面的現象。
文件的讀取
在對文件內容進行讀取時也經常出現編碼問題。這里我們首先來了解一下文件編碼。
文件編碼即文件的編碼方式。嚴格意義上來說,文件沒有編碼之說,都是按二進制格式保存在硬盤中的,只是在寫入讀取時需使用對應的編碼進行處理,以便操作系統配合相關軟件/字體,繪制到屏幕中給人看。所以關鍵問題是得知道文件內容是使用什么方式編碼成二進制碼存入到磁盤中的。
Linux中Vim下可使用命令set fileencoding來查看文件編碼。
Windows中txt文件點擊“文件”–>“另存為”,查看“編碼”顯示的編碼方式(ANSI:非Unicode編碼方式,對于英文系統即ASCII編碼,中文系統則為GB2312或Big5編碼;其余三種為“Unicode”(對應UTF-16 LE)、“Unicode big endian”(對應UTF-16 BE)和“UTF-8”)。
知道文件編碼方式后,只需要在讀取文件時使用相同的編碼方式對內容進行解碼就能獲得正確的文件內容。
# _*_ coding:utf-8 _*_
input_stream=open('temp.txt','w')
str1 = "你好"
input_stream.write(str1)#使用utf-8的編碼方式將內容寫入文件
input_stream.close()
input_stream = open('temp.txt','r')
line = input_stream.readline()
print line.decode('utf-8') #讀取utf-8編碼的文件需按utf-8解碼
但很多情況下我們無從知曉文件的編碼方式,此時可以使用python提供的Chardet包。
Character encoding auto-detection(自動字符探測器),Python中一個強力的編碼檢測包。使用方式非常簡單。
Import chardet
f = open('file','r')
fencoding = chardet.detect(f.read())
print fencoding
#fencoding:{'confidence':0.96630842899499614,'encoding':'GB2312'}}
#表示f中的內容使用“GB2312”編碼的概率為0.966
知道字符串的編碼后就可以利用decode和encode實現編碼的轉換得到正確的文件內容了。
因此,Python中的編碼問題解決方式總結起來就是:保證字符串的編碼及解碼方式一致,了解了文中提到相關知識相信能解決Python中大部分的編碼問題了。
總結
以上是生活随笔為你收集整理的python安全编码问题_浅谈Python中的编码问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: idea 用iterm 终端_帅气逼人的
- 下一篇: 口的内存映射 stm32f7_STM32