Python Unicode ASCII,序数超出范围,令人沮丧的错误
这是我的问题……
数据库里的所有内容都是用unicode格式存储的。
hashlib.sha256().digest()这个函数接受字符串并返回字符串。
当我试图用数据来计算哈希值时,出现了著名的错误:
UnicodeDecodeError: 'ascii' codec can't decode byte 0x90 in position 1: ordinal not in range(128)
这是我的数据
>>> db_digest
u"'\x90\x017~1\xe0\xaf4\xf2\xec\xd5]:j\xef\xe6\x80\x88\x89\xfe\xf7\x99,c\xff\xb7\x06hXR\x99\xad\x91\x93lM:\xafT\xc9j\xec\xc3\xb7\xea[\x80\xe0e\xd6\\\xd8\x16'\xcb6\xc8\xaa\xdf\xc9 :\xff"
>>>
>>> hashlib.sha256(db_digest)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\x90' in position 1: ordinal not in range(128)
>>>
>>> asc_db_digest
"'\x90\x017~1\xe0\xaf4\xf2\xec\xd5]:j\xef\xe6\x80\x88\x89\xfe\xf7\x99,c\xff\xb7\x06hXR\x99\xad\x91\x93lM:\xafT\xc9j\xec\xc3\xb7\xea[\x80\xe0e\xd6\\\xd8\x16'\xcb6\xc8\xaa\xdf\xc9 :\xff"
>>> hashlib.sha256(asc_db_digest)
<sha256 HASH object @ 0x7f7da0f04300>
所以我想要的就是找到一种方法,把db_digest转换成asc_db_digest。
编辑 我重新表述了一下问题,因为我发现自己一开始没有正确理解问题。
3 个回答
1
这个哈希值会包含一些“字符”,它们的范围是0到255。这些都是有效的Unicode字符,但它并不是一个Unicode字符串。你需要以某种方式进行转换。最好的办法是把它编码成像base64这样的格式。
还有一种比较“hacky”的方法,可以直接把返回的字节转换成一个伪Unicode字符串,正如你的数据库似乎在做的那样:
hash_unicode = u''.join([unichr(ord(c)) for c in hash_digest])
你也可以反过来做,但这样更危险,因为这个“字符串”会包含一些超出ASCII范围(0-127)的字符,使用时可能会出错。
asc_db_digest = ''.join([chr(ord(c)) for c in db_digest])
3
哈希函数是处理字节的(在Python 2.x中是bytes
和str
),而不是处理字符串的(在2.x中是unicode
,在3.x中是str
)。所以,你必须提供字节。可以试试:
hashlib.sha1(salt.encode('utf-8') + data).digest()
5
如果你有一个只包含从0到255(字节)的unicode字符串,你可以使用raw_unicode_escape编码把它转换成Python的字符串:
>>> db_digest = u"'\x90\x017~1\xe0\xaf4\xf2\xec\xd5]:j\xef\xe6\x80\x88\x89\xfe\xf7\x99,c\xff\xb7\x06hXR\x99\xad\x91\x93lM:\xafT\xc9j\xec\xc3\xb7\xea[\x80\xe0e\xd6\\\xd8\x16'\xcb6\xc8\xaa\xdf\xc9 :\xff"
>>> hash_digest = "'\x90\x017~1\xe0\xaf4\xf2\xec\xd5]:j\xef\xe6\x80\x88\x89\xfe\xf7\x99,c\xff\xb7\x06hXR\x99\xad\x91\x93lM:\xafT\xc9j\xec\xc3\xb7\xea[\x80\xe0e\xd6\\\xd8\x16'\xcb6\xc8\xaa\xdf\xc9 :\xff"
>>> db_digest.encode('raw_unicode_escape')
"'\x90\x017~1\xe0\xaf4\xf2\xec\xd5]:j\xef\xe6\x80\x88\x89\xfe\xf7\x99,c\xff\xb7\x06hXR\x99\xad\x91\x93lM:\xafT\xc9j\xec\xc3\xb7\xea[\x80\xe0e\xd6\\\xd8\x16'\xcb6\xc8\xaa\xdf\xc9 :\xff"
>>> db_digest.encode('raw_unicode_escape') == hash_digest
True