python版本坑:md5例子(python2與python3中md5區(qū)別)
起步
對(duì)于一些字符,python2和python3的md5加密出來(lái)是不一樣的.
# python2.7
pwd = "xxx" + chr(163) + "fj"
checkcode = hashlib.md5(pwd).hexdigest()
print checkcode # ea25a328180680aab82b2ef8c456b4ce
# python3.6
pwd = "xxx" + chr(163) + "fj"
checkcode = hashlib.md5(pwd.encode("utf-8")).hexdigest()
print(checkcode) # b517e074034d1913b706829a1b9d1b67
按代碼差異來(lái)將,就是在python3中需要對(duì)字符串進(jìn)行 encode 操作,如果沒(méi)有則會(huì)報(bào)錯(cuò):
checkcode = hashlib.md5(pwd).hexdigest() TypeError: Unicode-objects must be encoded before hashing
這是因?yàn)榧用軙r(shí)需要將字符串轉(zhuǎn)化為 bytes 類型,3默認(rèn)編碼是 utf-8 .所以我用utf-8進(jìn)行解碼.
分析
如果字符串中沒(méi)有 chr(163) ,那么兩個(gè)版本結(jié)果是一致的,也就是說(shuō)問(wèn)題出在這個(gè)chr(163)中:
# python2.7 >>> chr(163) '\xa3' # python3.6 >>> chr(163) '\xa3'
在這里說(shuō)明通過(guò) chr 得到的結(jié)果是一致的, 將它轉(zhuǎn)為 bytes 類型看看:
# python2.7 >>> bytes(chr(163)) '\xa3' # python3.6 >>> chr(163).encode() b'\xc2\xa3'
python3中,在 num<128 的時(shí)候,使用 chr(num).encode('utf-8') 得到的是 一個(gè) 字符的ascii十六進(jìn)制,而 num>128 的時(shí)候,使用 chr(num).encode('utf-8') 得到的是 兩個(gè) 字節(jié)的ascii十六進(jìn)制.
解決
改用 latin1 編碼進(jìn)行解碼:
# python3.6
pwd = "xxx" + chr(163) + "fj"
checkcode = hashlib.md5(pwd.encode("latin1")).hexdigest()
print(checkcode) # ea25a328180680aab82b2ef8c456b4ce
額外
為什么是 latin1 編碼呢.答案還是挺有意思的.
先說(shuō)chr函數(shù),通過(guò) help(chr) 可以查看:
chr(...) chr(i) -> Unicode character Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.
意思是它返回Unicode編碼中指定位置的一個(gè)字符.python3內(nèi)部也是用Unicode表示左右字符,即str類型.而通過(guò)encode后會(huì)編碼成 bytes 類型.
ascii編碼中每個(gè)字符編碼是一個(gè)byte,但只有1-127. 超過(guò)的部分128-255則屬于 Extended ASCII ,python3 中默認(rèn)的ascii中不包含這部分,所以如果執(zhí)行 chr(163).encode("ascii") 就會(huì)報(bào)錯(cuò) 'ascii' codec can't encode character '\xa3' in position 3: ordinal not in range(128)
因此需要一個(gè)含有128-255中的部分字符的編碼,且采用1個(gè)Byte固定大小編碼,比如ISO 8859-1,也就是 latin1.當(dāng)然還有其他編碼如cp1252也包含這些字符的.
相關(guān)文章
Jupyter Notebook內(nèi)使用argparse報(bào)錯(cuò)的解決方案
這篇文章主要介紹了在Jupyter Notebook內(nèi)使用argparse報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
在python 中split()使用多符號(hào)分割的例子
今天小編就為大家分享一篇在python 中split()使用多符號(hào)分割的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07
Python機(jī)器學(xué)習(xí)工具scikit-learn的使用筆記
這篇文章主要介紹了Python機(jī)器學(xué)習(xí)工具scikit-learn的使用筆記,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2021-01-01
Python自動(dòng)化實(shí)現(xiàn)日?qǐng)?bào)數(shù)據(jù)可視化
這篇文章主要為大家詳細(xì)介紹了如何使用Python實(shí)現(xiàn)自動(dòng)化生成日?qǐng)?bào)數(shù)據(jù)可視化,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-02-02
Python函數(shù)常見(jiàn)幾種return返回值類型
本文主要介紹了Python函數(shù)常見(jiàn)幾種return返回值類型,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01
Django2 連接MySQL及model測(cè)試實(shí)例分析
這篇文章主要介紹了Django2 連接MySQL及model測(cè)試,結(jié)合實(shí)例形式分析了Django2框架使用pymysql庫(kù)進(jìn)行mysql數(shù)據(jù)庫(kù)連接與model調(diào)用測(cè)試方法,需要的朋友可以參考下2019-12-12
python 與GO中操作slice,list的方式實(shí)例代碼
這篇文章主要介紹了python 與GO中操作slice,list的方式實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03
python之ImportError:模塊引入異常問(wèn)題
這篇文章主要介紹了python之ImportError:模塊引入異常問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06

