中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

由 Python2 和 Python3 中 socket.inet_aton() 實現不同引發的血案

發布時間:2020-07-05 08:11:22 來源:網絡 閱讀:848 作者:sylan215 欄目:編程語言

這幾天在做一個功能實現的時候,需要把別人用 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)

總結:

  1. Python3 新增了 bytes 類型,對于 bytes 的轉換邏輯要特別清楚,這地方涉及了編碼類型,要特別關注;
  2. 在使用一些函數前,一定要搞清楚這個函數的具體實現,必須清楚的知道使用了這個函數是什么效果,而不僅僅是看到暫時的效果,或者經驗主義的去調用(上面例子的最后一步,其實我一開始不是用的 binascii,而是用的現成的 md5 轉換函數,導致 encode() 成了 utf-8 格式,而浪費了不少時間去定位);
  3. 解決問題過程中,思路一定要清晰,不能靠猜,越猜越錯;
  4. 先弄明白問題的根本原因,直接從根源上去解決,比一步步的就錯解錯,效果更好。

本文原創發布于公眾號「sylan215」,十年測試老兵的原創干貨,關注我,漲姿勢!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

隆昌县| 临夏市| 河北区| 志丹县| 平果县| 库伦旗| 忻州市| 安丘市| 武川县| 中西区| 基隆市| 那曲县| 玉山县| 嫩江县| 辽源市| 盐池县| 嘉祥县| 天祝| 百色市| 怀仁县| 色达县| 靖江市| 楚雄市| 石城县| 洪洞县| 万年县| 常德市| 万源市| 且末县| 皮山县| 阜平县| 琼中| 扶风县| 双柏县| 桐梓县| 德格县| 凭祥市| 武宣县| 宝丰县| 棋牌| 喀喇|