2014-10-12 173 views
1

我想写一个函数来md5散列任何python对象。我想在python2和python3中返回相同的md5值。pickle.dumps兼容python2,3

我知道python3中的pickle.dumps,它返回字节,而在python2中,它返回str。正如你可以看到下面的代码给了我现在同样的字符串:

print([  pickle.dumps(obj, protocol = 2) ]) # in python2 
print([ str(pickle.dumps(obj, protocol = 2)) ]) # in python3 

两个给我:

['\x80\x02]q\x00(U\x011q\x01K\x02U\x013q\x02K\x04e.'] 

但问题是,在python3:

hashlib.md5.update(some_string) 

有被编码。如果我在python3中编码字符串,那么它不会给我与python2中相同的md5值。谁可以给我一个解决方案?感谢你们。

这里是我的代码:

from __future__ import print_function 
import hashlib 
import pickle 
import sys 

is_py2 = (sys.version_info[0] == 2) 

obj = ['1',2,'3',4] 
m = hashlib.md5() 

if is_py2:             # if it's python2 
    print( [  pickle.dumps(obj, protocol = 2) ]) 
    m.update(  pickle.dumps(obj, protocol = 2) ) 
else:               # if it's python3 
    print( [ str(pickle.dumps(obj, protocol = 2)) ]) 
    m.update(  pickle.dumps(obj, protocol = 2).encode("utf-8")) # I wish I could don not encode 

print(m.hexdigest()) 

回答

0

有一个班轮可以做2x和3x编码,你可以做任何编码。

>>> hashlib.new(algorithm, repr(object).encode()).hexdigest() 

请参见:https://github.com/uqfoundation/klepto/blob/master/klepto/crypto.py#L26的变量名的完整上下文......,看到该文件的其余部分上的编码,序列化等更多的抽象。所有工作在python 2.x和3.x.

我看到你想让Python 2.x和3.x返回相同的散列。嗯...我不认为这是有效的。如果它有任何机会,或者在2.x中返回相同的md5编码,就像它在3.x中一样,您可能必须先用reprpickle(协议2)或其他名称先打它。

Python 2.7.8 (default, Jul 13 2014, 02:29:54) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import klepto 
>>> klepto.crypto.hash(klepto.crypto.pickle(object), algorithm='md5') 
'ee16782749cb00e4b66922df545877f0' 

所以,咸菜和md5似乎并没有工作,一般不应该因为某些对象2.x和3.x之间的更改(例如objecttype现在是一个class)。这也意味着repr或其他类似的东西也不会作为编码器工作。

Python 3.3.5 (default, Mar 10 2014, 21:37:38) 
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import klepto 
>>> klepto.crypto.hash(klepto.crypto.pickle(object), algorithm='md5') 
'35eb4c374cafe09c8ac01661701b6b6e' 

也许有klepto的其他编码器,将你的工作之一。

0

1)pickle.dumps会返回一个字节的字符串,所以你的打印是错误的。

2)如果由于某种原因,你在unicode字符串上有这样的内容,你不能使用多字节编解码器作为utf-8(默认)。

foo = '\x80\x02]q\x00(U\x011q\x01K\x02U\x013q\x02K\x04e.'.encode('latin-1') 

latin-1将有一个1对1映射,所以你用正确的字节结束。


PS:你为什么在打印中使用列表?也许你正在寻找print(repr(...))

+0

请你给我的代码,使对象的MD5值在两个py2,3相同? – MacSanhe 2014-10-12 12:50:22