le codage base64 des chaînes unicode python 2.7

J'ai une chaîne unicode récupérées à partir d'un service web à l'aide de la demande module, qui contient les octets d'un document binaire (PCL, comme il arrive). L'un de ces octets est la valeur 248, et à tenter de les encoder en base64, il conduit à l'erreur suivante:

In [68]: base64.b64encode(response_dict['content']+'\n')
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
C:\...\<ipython-input-68-8c1f1913eb52> in <module>()
----> 1 base64.b64encode(response_dict['content']+'\n')

C:\Python27\Lib\base64.pyc in b64encode(s, altchars)
     51     """
     52     # Strip off the trailing newline
---> 53     encoded = binascii.b2a_base64(s)[:-1]
     54     if altchars is not None:
     55         return _translate(encoded, {'+': altchars[0], '/': altchars[1]})

UnicodeEncodeError: 'ascii' codec can't encode character u'\xf8' in position 272: ordinal not in range(128)

In [69]: response_dict['content'].encode('base64')
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
C:\...\<ipython-input-69-7fd349f35f04> in <module>()
----> 1 response_dict['content'].encode('base64')

C:\...\base64_codec.pyc in base64_encode(input, errors)
     22     """
     23     assert errors == 'strict'
---> 24     output = base64.encodestring(input)
     25     return (output, len(input))
     26

C:\Python27\Lib\base64.pyc in encodestring(s)
    313     for i in range(0, len(s), MAXBINSIZE):
    314         chunk = s[i : i + MAXBINSIZE]
--> 315         pieces.append(binascii.b2a_base64(chunk))
    316     return "".join(pieces)
    317

UnicodeEncodeError: 'ascii' codec can't encode character u'\xf8' in position 44: ordinal not in range(128)

Je trouve cela un peu surprenant, car 248 est dans la gamme d'un octet non signé (et peut être tenu dans une chaîne d'octets), mais ma vraie question est: quelle est la meilleure ou la bonne façon de coder cette chaîne?

Mon travail actuel est ceci:

In [74]: byte_string = ''.join(map(compose(chr, ord), response_dict['content']))

In [75]: byte_string[272]
Out[75]: '\xf8'

Cela semble fonctionner correctement, et la byte_string est susceptible d'être codé en base64, mais il semble qu'il devrait y avoir une meilleure façon. Qui est là?

248 peut être dans la gamme d'un octet non signé, mais il n'est pas dans la gamme de standards ASCII [0-127].
Un vrai et bon point, mais ça n'explique toujours pas le problème, exactement la même valeur, dans le cadre d'une chaîne d'octets ne résulte pas d'une erreur.
Voir ma réponse 🙂 Ce que vous avez fait est de prendre le codepoints de la unicode chaîne et de les traiter comme des octets. C'est... louche, au mieux, puisque vous êtes il n'y a aucune garantie de la codepoints sont encore dans la gamme de 0 à 255. Ce qui est encore pire, c'est que personne d'autre ne saura comment interpréter la chaîne d'octets plus tard, puisque c'est dans une coutume, pas défini de codage.
je le répète: ces données ne sont pas de code de caractère de points, ce sont des données binaires.

OriginalL'auteur Marcin | 2012-03-05