valueInserted = zlib.compress('a') = 'x\x9cK\x04\x00\x00b\x00b'
Обратите внимание, что это объект str. Вы говорите, что «вставили его в столбец mysql типа blob, используя кодировку utf-8». Поскольку сжатая строка является двоичной, а не текстовой, "BLOB" является подходящим типом столбца, но ЛЮБОЕ кодирование или другое преобразование - очень плохая идея. Вы должны иметь возможность восстанавливать из базы данных ТОЧНО вплоть до последнего бита того, что вы вставили, иначе распаковка завершится ошибкой, либо (менее вероятно, но хуже) молча производя мусор.
Вы говорите, что возвращаетесь после любого процесса, через который вы проходите, вставляя его и снова извлекая:
valueFromSqlColumn = u'x\x9cK\x04\x00\x00b\x00b'
Внимательно отметьте, что есть только одна крошечная визуальная разница: u'что-то' вместо 'что-то'. Это делает его объектом unicode. Основываясь на ваших собственных доказательствах, «возвращается как UTF-8» неверно. Объект unicode и объект str, закодированный в utf8, — это не одно и то же.
Угадайте 1: вставьте как необработанную строку, извлеките с декодированием latin1.
Угадайте 2: вставьте как сжатый.decode('latin1').encode('utf8'), извлеките с декодированием utf8.
Вам действительно нужно понимать процесс вставки и извлечения, в том числе то, что кодирует и декодирует по умолчанию.
Тогда вам действительно нужно исправить свой код. Однако тем временем вы, вероятно, можете собрать то, что у вас есть.
Обратите внимание:
>>> valueFromSqlColumn = u'x\x9cK\x04\x00\x00b\x00b'
>>> all(ord(char) <= 255 for char in valueFromSqlColumn)
True
Проведите несколько испытаний с более сложным вводом, чем «а». Если, как я предполагаю, вы видите, что все символы Юникода имеют порядковый номер в диапазоне (256), то у вас есть простой кладж:
>>> compressed = valueFromSqlColumn.encode('latin1')
>>> compressed
'x\x9cK\x04\x00\x00b\x00b'
>>> zlib.decompress(compressed)
'a'
Почему это работает, так это то, что кодирование/декодирование Latin1 не меняет порядковый номер. Вы можете восстановить исходное сжатое значение:
>>> compressed2 = ''.join(chr(ord(uc)) for uc in valueFromSqlColumn)
>>> compressed2
'x\x9cK\x04\x00\x00b\x00b'
>>> compressed2 == compressed
True
если вы думаете, что использование .encode('latin1') слишком похоже на вуду.
Если описанное выше не работает (т. е. некоторые порядковые номера не находятся в диапазоне (256)), вам потребуется создать небольшой исполняемый скрипт, который показывает точно и воспроизводимо, как вы сжимаете, вставляя в базу данных и извлечение из базы данных... посыпьте свой код большим количеством print "variable", repr(variable)
, чтобы вы могли видеть, что происходит.
person
John Machin
schedule
24.10.2009