在這裏先說明標題python爲何沒有指明版本。由於我此次講述的一個把py2代碼改成py3代碼的真實實例。python
筆者有個項目,筆者的python項目須要與後端.Net用md5加密對接api。結果調試了很是久後終於好了。如今筆者的代碼基本改用py3,因而嘗試升級下。結果.....嗯~因而寫下本文,分享下關於python版本間 字典序列 json轉字符串 md5加密 跨語言對接 遇到的各類各樣的坑!!!c++
原本想分文章講述的。可是畢竟是一個項目實例。就放在一塊兒說了。至於.Net調試時打印的文本是怎麼樣的,我就只是描述下好了。.Net筆者不會,並且項目已久,也沒時間找別人對接調試了。json
假設咱們的數據是後端
(ps: 有人說我e打錯爲el了。其實我是故意的!!!若是是e,py2下字典序列就會看上去有一點規律可尋。爲了不有人鑽空子,只能這樣了)api
d = { 'a':1, 'b':2, 'c':3, 'd':4, 'el':5, 'f':6, 'g':7, }
如今要作的是服務器
python客戶端 | .Net服務器 |
一、把 字典 轉成 字符串 | |
二、把 字符串 用 md5加密 | |
三、把 加密結果 和 字符串 發給服務器(.net) | 3*、服務器 把字符串轉字典後,重複一、2 |
4*、服務器 匹配 原加密結果 與 本身計算的加密結果。相同則返回正確 |
爲了顯示版本我加上打印sys.version來區分版本。代碼十分簡單。可是結果卻顯然有問題。函數
import sys import json d = { 'a':1, 'b':2, 'c':3, 'd':4, 'el':5, 'f':6, 'g':7, } print(sys.version) print(json.dumps(d)) """ ----------py2------------- #py2的字典是無序的 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:25:58) [MSC v.1500 64 bit (AMD64)] {"a": 1, "el": 5, "c": 3, "b": 2, "d": 4, "g": 7, "f": 6} ----------py3------------- #py3的字典是有序的 3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)] {"a": 1, "b": 2, "c": 3, "d": 4, "el": 5, "f": 6, "g": 7} ----------.net---------------- .net的字符串在,和:後面是沒有空格的,並且是按順序的。下面的結果是基於之前對接的測試結果推測。 {"a":1,"b":2,"c":3,"d":4,"el":5,"f":6,"g":7} """
這裏之前py2對接的時候排查了很久!拿了電腦去雙雙一步步調試才知道緣由。測試
py2的字典是無序的,可是key不變且位置不變時,就算值改變,轉字符串的key順序是相對固定的。也就是說,還好只須要調試成功一次就好了(若是不加/改/刪key的話)。加密
解決方法有3種spa
讓服務器(.net)把dist的順序改成跟咱們轉字符串後的順序同樣。
ps:咱們當初是這樣解決啦。由於沒辦法且這樣最快解決問題。若是api是外部的話就GG了。
在python裏爲了應對這種狀況,在內置函數collections有OrderedDict(有序字典)建立有序字典。操做與使用和dist相似,十分方便。
ps:這是比較推薦的方法。可是當字典下還有字典的話,也會有問題。若是子字典是dist,則子dist依然是無序的。若是子字典是OrderedDict會把OrderedDict的類名也帶上。
import sys import collections d = collections.OrderedDict() d['a'] = 1 d['b'] = 2 d['c'] = 3 d['d'] = 4 d['el'] = 5 d['f'] = 6 d['g'] = 7 print(sys.version) print(json.dumps(d)) """ 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:25:58) [MSC v.1500 64 bit (AMD64)] {"a": 1, "b": 2, "c": 3, "d": 4, "el": 5, "f": 6, "g": 7} """
代碼不說了,就是本身模擬json把字典按本身順序拼接成字符串。不建議使用,很容易致使沒法解析回json的。
在python中,字典轉字符串不管在那個版本里, 和:後面都會有空格。所以,當python對接其餘語言時,若是對字典md5加密,則須要處理掉空格問題。
strings = strings.replace(': ',':').replace(', ',',')
簡單處理下就好。不要直接replace掉空格,由於內容字符串可能本來就有空格,例如英文名、地址之類的。
在py3中md5加密必須把字符串轉成byte類型才能加密。py2中不強制要求。基本寫法是
import hashlib string = 'xxxx' m = hashlib.md5() m.update(string.encode(encoding='utf-8')) m.hexdigest()
在沒有中文的狀況下,py2與py3的結果是必定相同的。有些文章說,有中文時結果會不同。可是我實際測試結果是同樣的。惟一區別只有encode的結果,md5結果同樣。不過你們仍是留意下。
import sys import hashlib print(sys.version) s = 'kid' s1 = s.encode(encoding='utf-8') print(s1) m = hashlib.md5() m.update(s1) print(m.hexdigest()) s = u'中文' s1 = s.encode(encoding='utf-8') print(s1) m = hashlib.md5() m.update(s1) print(m.hexdigest()) """ ---------py2-------- 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:25:58) [MSC v.1500 64 bit (AMD64)] kid 7de007e43f108e4b54b079f66e4285d8 涓枃 a7bac2239fcdcb3a067903d8077c4a07 ---------py3--------- 3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)] b'kid' 7de007e43f108e4b54b079f66e4285d8 b'\xe4\xb8\xad\xe6\x96\x87' a7bac2239fcdcb3a067903d8077c4a07 """
以上面的例子爲例。py2的正確加密方法是
import sys import json import collections d = collections.OrderedDict() d['a'] = 1 d['b'] = 2 d['c'] = 3 d['d'] = 4 d['el'] = 5 d['f'] = 6 d['g'] = 7 print(sys.version) string = json.dumps(d).replace(': ',':').replace(', ',',') print(string) m = hashlib.md5() m.update(string.encode(encoding='utf-8')) print(m.hexdigest()) """ 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:25:58) [MSC v.1500 64 bit (AMD64)] {"a":1,"b":2,"c":3,"d":4,"el":5,"f":6,"g":7} d94f30c6cc9b1fc05ddcb04c920d5351 """
py3的正確加密方法是
import hashlib import sys import json d = { 'a':1, 'b':2, 'c':3, 'd':4, 'el':5, 'f':6, 'g':7, } print(sys.version) string = json.dumps(d).replace(': ',':').replace(', ',',') print(string) m = hashlib.md5() m.update(string.encode(encoding='utf-8')) print(m.hexdigest()) """ 3.7.2 (tags/v3.7.2:9a3ffc0492, Dec 23 2018, 23:09:28) [MSC v.1916 64 bit (AMD64)] {"a":1,"b":2,"c":3,"d":4,"el":5,"f":6,"g":7} d94f30c6cc9b1fc05ddcb04c920d5351 """
若是跨語言的加密匹配這樣是正確的。對於python對python之間,只要字典順序結構相同,同版本之間的md5校驗是同樣的。
據我所知c++ .Net的json字符串 , : 都是沒有空格的。具體要api實測時調試才清楚。
以上就是我項目中遇到的問題和處理方式。
1字典順序問題 (py2最好用OrderedDict代替dist)
2md5加密問題 (不管py2仍是py3都加上.encode(encoding='utf-8')保險)
3json轉字符串,跨語言對接問題問題 (對接要實際調試下,就python對接.Net而言,須要處理掉字符串: , 後面的空格,字符串才徹底一致,MD5加密就更不用說了)
轉載請註明出處:https://my.oschina.net/jacky326/blog/3039177