Python Unicode Ascii, Ordinal not In range, расстраивающая ошибка - PullRequest
3 голосов
/ 11 февраля 2012

Вот моя проблема ...

База данных хранит все в юникоде.hashlib.sha256 (). digest () принимает str и возвращает str.

Когда я пытаюсь заполнить хеш-функцию данными, я получаю известную ошибку:

UnicodeDecodeError: 'ascii' codec can't decode byte 0x90 in position 1: ordinal not in range(128)

Это мойdata

>>> 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

Edit Я перефразировал вопрос, как кажется, я не узналпроблема правильно на первом месте.

Ответы [ 3 ]

5 голосов
/ 11 февраля 2012

Если у вас есть строка Unicode, которая содержит только кодовые точки от 0 до 255 (байтов), вы можете преобразовать ее в строку Python, используя кодировку raw_unicode_escape:

>>> 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
3 голосов
/ 11 февраля 2012
Хеши

работают с байтами (bytes, str в Python 2.x), а не со строками (unicode в 2.x, str в 3.x).Таким образом, вы должны предоставить байты в любом случае.Попробуйте:

hashlib.sha1(salt.encode('utf-8') + data).digest()
1 голос
/ 11 февраля 2012

Хеш будет содержать «символы», которые находятся в диапазоне 0-255. Все это допустимые символы Юникода, но это не строка Юникода. Вы должны преобразовать это как-то. Лучшим решением было бы закодировать его в нечто вроде base64 .

Существует также хакерское решение для преобразования байтов, возвращаемых непосредственно, в строку псевдо-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])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...