valueInserted = zlib.compress('a') = 'x\x9cK\x04\x00\x00b\x00b'
Notez que ceci est un str objet. Vous dites que vous l'avez "inséré dans une colonne mysql de type blob, en utilisant l'encodage utf-8". Comme la chaîne compressée est binaire, pas de texte, "blob" est un type de colonne approprié, mais tout encodage ou autre transformation est une très mauvaise idée. Vous devez être capable de récupérer de la base de données EXACTEMENT jusqu'au dernier bit que vous avez inséré, sinon la décompression échouera, soit en augmentant une erreur ou (moins probablement, mais pire) en produisant silencieusement des ordures.
Vous dites que vous revenez après tout processus que vous passez par à insérer et extraire est à nouveau:
valueFromSqlColumn = u'x\x9cK\x04\x00\x00b\x00b'
Notez soigneusement qu'il n'y a qu'une seule petite différence visuelle: u'something « au lieu de » quelque chose'. Cela en fait un objet unicode. Sur la base de vos propres preuves jusqu'à présent, "revient en UTF-8" n'est pas correct. Un objet unicode et un objet str codé en utf8 ne sont pas la même chose.
Devinez 1: insérer comme chaîne brute, extraire avec le décodage latin1. Devinez 2: insérer comme compressed.decode ('latin1'). Encoder ('utf8'), extraire avec le décodage utf8.
Vous avez vraiment besoin de comprendre le processus d'insertion et d'extraction, y compris ce qui code et décode par défaut.
Ensuite, vous devez vraiment corriger votre code. Cependant, entre-temps, vous pouvez probablement mélanger ce que vous avez.
Notez ceci:
>>> valueFromSqlColumn = u'x\x9cK\x04\x00\x00b\x00b'
>>> all(ord(char) <= 255 for char in valueFromSqlColumn)
True
Faites quelques essais avec entrée plus compliqué que 'a'. Si, comme je suppose que, vous voyez que tous les caractères unicode ont un ordinal dans la plage (256), alors vous avez un exemple simple bidouille:
>>> compressed = valueFromSqlColumn.encode('latin1')
>>> compressed
'x\x9cK\x04\x00\x00b\x00b'
>>> zlib.decompress(compressed)
'a'
Pourquoi cela fonctionne est que Latin1 encodage/décodage ne change pas l'ordinal. Vous pouvez récupérer la valeur compressée originale:
>>> compressed2 = ''.join(chr(ord(uc)) for uc in valueFromSqlColumn)
>>> compressed2
'x\x9cK\x04\x00\x00b\x00b'
>>> compressed2 == compressed
True
si vous pensez à l'aide .encode (« latin1 ») est trop comme voodoo.
Si ce qui précède ne fonctionne pas (autrement dit certains ordinaux ne sont pas dans la plage (256)), alors vous aurez besoin pour produire un petit script qui montre runnable exactement et comment vous reproductible comprimant, l'insertion dans la base de données , et récupérer de la base de données ... saupoudrer beaucoup de print "variable", repr(variable)
autour de votre code afin que vous puissiez voir ce qui se passe.
La chaîne ne revient pas en UTF-8, elle revient comme ** un objet unicode **. C'est important, et un malentendu très commun. – u0b34a0f6ae