为什么Python的Hashlib没有强类型?

时间:2011-08-01 16:47:38

标签: python hashlib

Python应该是强类型的。

例如:'abc'['1']将不起作用,因为您需要在那里提供一个整数,而不是字符串。将引发错误,您可以继续纠正它。

但是hashlib并非如此。确实,请尝试以下方法:

import hashlib
hashlib.md5('abc') #Works OK        

hashlib.md5(1) 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: md5() argument 1 must be string or read-only buffer, not int

hashlib.md5(u'abc') #Works, but shouldn't : this is unicode, not str.

haslib.md5(u'é')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 0: ordinal not in range(128)

当然,它不会因TypeError而失败,而是因为UnicodeEncodeError。当您尝试将unicode编码为字符串时,应该会引发UnicodeEncodeError

我认为,当我的猜测是Hashlib默默地试图将unicode转换为字符串时,我并没有太离真相。

现在。我同意,hashlib指出hashlib.md5()的参数应该是一个字符串或一个只读字符串的只读缓冲区。 但这实际上表明它实际上并非如此:hashlib.md5()可以正常使用字符串,而这就是它。

当然,这导致的主要问题是你会得到一些unicode字符串的异常,而不是其他的。

这引出了我的问题。首先,您是否有关于为什么hashlib实现此行为的解释?第二,它被认为是一个问题吗?第三,有没有办法在不改变模块本身的情况下解决这个问题?

Hashlib基本上就是一个例子,有几个其他模块在提供unicode字符串时表现相同 - 这会让你感到一种不舒服的情况,你的程序将使用ASCII输入但完全失败并带有重音。

2 个答案:

答案 0 :(得分:12)

它不仅仅是hashlib - Python 2通过尝试将其编码为ascii来处理许多地方的Unicode。这是Python 3的重大变化之一。

在Python 3中,字符串是unicode,它们的行为与预期的一样:没有自动转换为字节,如果要使用字节(例如,用于MD5散列),则必须对它们进行编码。我相信有些使用sys.setdefaultencoding的hack在Python 2中启用了这种行为,但我建议不要在生产中使用它们,因为它们会影响在该Python实例中运行的任何代码。

答案 1 :(得分:2)

这是Python 2.x C API的结果,可以方便地将Unicode对象传递给期望字符串的C API。

请参阅_hashopenssl.c中的PyArg_ParseTuple *调用。

在解析's''参数时,它会尝试将Unicode对象编码为字节字符串。如果无法编码,则会引发错误。正确的做法是在尝试在只有原始字节流有意义的上下文中使用任何Unicode之前,始终调用.encode('utf-8')或应用程序所需的任何其他编解码器。

Python 3.x解决了这个问题。相反,你总会得到一个友好的:

TypeError:必须在散列之前对Unicode对象进行编码

而不是任何自动编码。