您好,登錄后才能下訂單哦!
這幾天在做一個功能實現的時候,需要把別人用 Python2.6 寫好的腳步轉成 Python3.4 實現,大部分地方轉化都沒啥問題,但是在 socket.inet_aton() 轉化的過程中出了點問題,花費我不少的精力去解決,先做個記錄備忘,同時給后續需要的人做個提醒。
首先說一下,我在解決這個問題前期的思路有點問題,所以請關注最后的總結。
需求目的:把一個 ip 地址使用 socket.inet_aton() 轉化后和一個字符串組合,然后算出 MD5。
下面是 Python2.6 的實現代碼:
#!python2
# -*- coding: utf-8 -*-
import socket
import hashlib
if __name__ == '__main__':
ip = '192.168.1.12'
base_str = 'testSTR'
ip_md5 = hashlib.md5(socket.inet_aton(ip) + base_str).digest().encode('hex')
print(ip_md5)
運行后的輸出結果為:
fc138bb4748a18f885cc321c2c6396e2
如果原封不動的使用 Python3.4 運行后,報錯如下:
Traceback (most recent call last):
File "socket34.py", line 25, in <module>
test1()
File "socket34.py", line 10, in test1
ip_md5 = hashlib.md5(socket.inet_aton(ip) + base_str).digest().encode('hex')
TypeError: can't concat bytes to str
提示說的是,socket.inet_aton(ip) 的返回值是 bytes 類型,所以不能和 str 類型的 base_str 直接進行連接操作。
也就是說 Python2.6 和 python3.4 中對于 socket.inet_aton(ip) 的實現是有差異的,查官方文檔吧。
python2.6文檔說明:
socket.inet_aton(ip_string)
Convert an IPv4 address from dotted-quad string format (for example, ‘123.45.67.89’) to 32-bit packed binary format, as a bytes object four characters in length.
python3.4 文檔說明:
socket.inet_aton(ip_string)
Convert an IPv4 address from dotted-quad string format (for example, ‘123.45.67.89’) to 32-bit packed binary format, as a string four characters in length.
好吧,返回值類型不同,為了保證和原腳本邏輯一致,我就做個轉化,把 bytes 主動轉換為 str 類型再連接,修改后的代碼如下:
#!python3
# -*- coding: utf-8 -*-
import socket
import hashlib
if __name__ == '__main__':
ip = '192.168.1.12'
base_str = 'testSTR'
str_md5 = socket.inet_aton(ip).decode('gbk') + base_str
ip_md5 = hashlib.md5(str_md5).digest().encode('hex')
print(ip_md5)
代碼通過 decode 把 bytes 使用 gbk 的方式解碼成 str,至于為什么用 gbk,是因為我對比了下,只有 gbk 編碼方式解碼后的輸出才和 python2.6 中的 str 返回值結果一致。
行,趕緊運行一把試試看。。。還是報錯了,這次的報錯內容變了:
Traceback (most recent call last):
File "socket34.py", line 34, in <module>
test1()
File "socket34.py", line 12, in test1
ip_md5 = hashlib.md5(str_md5).digest().encode('hex')
TypeError: Unicode-objects must be encoded before hashing
看起來 hashlib.md5() 在 Python2.6 和 Python3.4 中的實現也有差異,繼續看文檔。
python2.6文檔說明:
You can now feed this object with arbitrary strings using the update() method.
python3.4 文檔說明:
You can now feed this object with bytes-like objects (normally bytes) using the update() method.
依然是編碼格式的問題,Python2.6 中參數傳入的是 str,但是 Python3.4 中參數需要傳入 bytes,那就繼續轉碼吧。
再次轉碼后的代碼如下:
#!python3
# -*- coding: utf-8 -*-
import socket
import hashlib
if __name__ == '__main__':
ip = '192.168.1.12'
base_str = 'testSTR'
str_md5 = socket.inet_aton(ip).decode('gbk') + base_str
ip_md5 = hashlib.md5(str_md5.encode('gbk')).digest().encode('hex')
print(ip_md5)
運行后再次報錯:
Traceback (most recent call last):
File "socket34.py", line 33, in <module>
test1()
File "socket34.py", line 11, in test1
ip_md5 = hashlib.md5(str_md5.encode('gbk')).digest().encode('hex')
AttributeError: 'bytes' object has no attribute 'encode'
好吧,繼續看文檔。
python2.6文檔說明:
hash.digest()
Return the digest of the strings passed to the update() method so far. This is a string of digest_size bytes which may contain non-ASCII characters, including null bytes.
python3.4 文檔說明:
hash.digest()
Return the digest of the data passed to the update() method so far. This is a bytes object of size digest_size which may contain bytes in the whole range from 0 to 255.
這次更嚴重,encode() 直接用不了,換方法吧,更新后的代碼如下:
#!python3
# -*- coding: utf-8 -*-
import socket
import hashlib
import binascii
if __name__ == '__main__':
ip = '192.168.1.12'
base_str = 'testSTR'
str_md5 = socket.inet_aton(ip).decode('gbk') + base_str
ip_md5 = binascii.hexlify(hashlib.md5(str_md5.encode('gbk')).digest()).decode()
print(ip_md5)
運行后的輸出結果:
fc138bb4748a18f885cc321c2c6396e2
終于得到了最終結果,激動,不過再回頭一看,如果知道這幾個函數的使用方式的話,就不需要 decode() 然后又 encode(),比如稍微優化后的代碼如下:
#!python3
# -*- coding: utf-8 -*-
import socket
import hashlib
import binascii
if __name__ == '__main__':
ip = '192.168.1.12'
base_str = 'testSTR'
str_md5 = socket.inet_aton(ip) + base_str.encode()
ip_md5 = binascii.hexlify(hashlib.md5(str_md5).digest()).decode()
print(ip_md5)
總結:
本文原創發布于公眾號「sylan215」,十年測試老兵的原創干貨,關注我,漲姿勢!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。