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à?
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
Vous devez vous connecter pour publier un commentaire.
Puisque vous travaillez avec des données binaires, je ne suis pas sûr que c'est une bonne idée d'utiliser l'encodage utf-8. Je suppose que cela dépend de comment vous avez l'intention d'utiliser le base64 de la représentation. Je pense qu'il serait probablement mieux si vous pouvez récupérer les données sous forme d'octets de la chaîne et non pas une chaîne unicode. Je n'ai jamais utilisé les demandes de la bibliothèque, mais la navigation sur la documentation suggère qu'il est possible. Il y a des sections de parler de "Binaire Contenu de la Réponse" et "Brut de Contenu de la Réponse".
Vous devez vous assurer que les demandes de module n'a pas supposé que vous travaillez avec du texte, appliquer un codage par défaut, et de le décoder vos données binaires au format unicode. Si c'est le cas, vous avez de la difficulté. Pouvez-vous vérifier que le contenu est ce que vous attendez?
Avoir payé un peu plus d'attention pour les docs, il s'avère que les demandes me dit aussi de l'encodage qui est utilisé pour décoder la réponse à unicode, donc je peux fiable de toujours ré-encoder (et qu'une fois de plus, vous obtiendrez le même octets).
OriginalL'auteur
Vous avez un
unicode
chaîne que vous souhaitez encoder en base64. Le problème est queb64encode()
ne fonctionne que sur octets, pas caractères. Donc, vous avez besoin pour transformer votreunicode
chaîne (qui est une séquence de résumé Unicode codepoints) en une chaîne d'octets.La cartographie de l'abrégé des chaînes Unicode dans un béton de la série d'octets est appelé encodage. Python supporte plusieurs codages, je propose le plus largement utilisé l'encodage UTF-8:
Noter que celui qui est en train de décoder les octets également besoin de savoir quel est le codage a été utilisé pour obtenir un
unicode
chaîne via la complémentairedecode()
fonction:Un bon point de départ pour apprendre plus au sujet de l'Unicode et les codages est le Python docs, et cet article par Joel Spolsky.
Vous ne pouvez pas avoir un
unicode
chaîne de caractères contenant des données binaires. C'est une contradiction dans les termes! Si leunicode
de la chaîne d'octets sont censés représenter des données binaires (comme cela semble être le cas ici), il ne doit pas être stocké dans ununicode
objet que ce n'est pas vraiment Unicode à tous!Oui, c'est mon problème.
Pourquoi ne pas ajouter BOM? En fait, cette fonctionnalité permet de détecter si une chaîne de caractères UTF-8 ou pas.
Je pense que c'est mieux si les Nomenclatures ne sont généralement utilisés au début des fichiers; la surcharge et de la complexité de devoir vérifier les chaînes de partout pour une NOMENCLATURE semble trop élevé. J'ai eu le codage mixte, même si, la
-sig
un t ajouter la NOMENCLATURE.OriginalL'auteur
Je dirais d'abord encodage à quelque chose comme de l'UTF-8 avant l'encodage base64:
OriginalL'auteur
Il devrait être possible d'obtenir une réponse binaire des octets et passez le décodage et l'encodage des mesures entièrement. Il y a toujours une possibilité que
requests
va choisir un codage qui perd certaines données ou des erreurs dans l'aller-retour.Cette partie de la documentation appelé "Binaire Contenu De La Réponse" semble correspondre à votre problème parfaitement.
OriginalL'auteur
Si c'est du binaire de données...pourquoi coder/décoder? Spécialement le "base64.encodestring". Ci-dessous comment j'ai coder des images en base64 pour l'ajouter directement dans mon code python au lieu d'avoir des fichiers supplémentaires. 2.7.2 btw
OriginalL'auteur