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输入但完全失败并带有重音。
答案 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对象进行编码
而不是任何自动编码。