python版本坑:md5例子(python2與python3中md5區別)

這篇文章主要介紹了python版本坑:md5例子(python2與python3中md5區別),需要的朋友可以參考下
起步

對於一些字符,python2和python3的md5加密出來是不一樣的.

# 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

按代碼差異來將,就是在python3中需要對字符串進行 encode 操作,如果沒有則會報錯:

checkcode = hashlib.md5(pwd).hexdigest()
TypeError: Unicode-objects must be encoded before hashing

這是因爲加密時需要將字符串轉化爲 bytes 類型,3默認編碼是 utf-8 .所以我用utf-8進行解碼.

分析

如果字符串中沒有 chr(163) ,那麼兩個版本結果是一致的,也就是說問題出在這個chr(163)中:

# python2.7
>>> chr(163)
'\xa3'
 
# python3.6
>>> chr(163)
'\xa3'

在這裏說明通過 chr 得到的結果是一致的, 將它轉爲 bytes 類型看看:

# python2.7
>>> bytes(chr(163))
'\xa3'
 
# python3.6
>>> chr(163).encode()
b'\xc2\xa3'

python3中,在 num<128 的時候,使用 chr(num).encode(‘utf-8’) 得到的是 一個 字符的ascii十六進制,而 num>128 的時候,使用 chr(num).encode(‘utf-8’) 得到的是 兩個 字節的ascii十六進制.

解決
改用 latin1 編碼進行解碼:

# python3.6
pwd = "xxx" + chr(163) + "fj"
checkcode = hashlib.md5(pwd.encode("latin1")).hexdigest()
print(checkcode)  # ea25a328180680aab82b2ef8c456b4ce

額外
爲什麼是 latin1 編碼呢.答案還是挺有意思的.

先說chr函數,通過 help(chr) 可以查看:

chr(...)
  chr(i) -> Unicode character
  Return a Unicode string of one character with ordinal i; 0 <= i <= 0x10ffff.

意思是它返回Unicode編碼中指定位置的一個字符.python3內部也是用Unicode表示左右字符,即str類型.而通過encode後會編碼成 bytes 類型.

ascii編碼中每個字符編碼是一個byte,但只有1-127. 超過的部分128-255則屬於 Extended ASCII ,python3 中默認的ascii中不包含這部分,所以如果執行 chr(163).encode(“ascii”) 就會報錯 ‘ascii’ codec can’t encode character ‘\xa3’ in position 3: ordinal not in range(128)

因此需要一個含有128-255中的部分字符的編碼,且採用1個Byte固定大小編碼,比如ISO 8859-1,也就是 latin1.當然還有其他編碼如cp1252也包含這些字符的.

推薦我們的python學習基地,點擊進入,看老程序是如何學習的!從基礎的python腳本、爬蟲、django、數據挖掘等編程技術,工作經驗,還有前輩精心爲學習python的小夥伴整理零基礎到項目實戰的資料,!每天都有程序員定時講解Python技術,分享一些學習的方法和需要留意的小細節

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章