Comment puis-je écrire des données binaires brutes en Python?
J'ai un programme en Python qui stocke et écrit des données dans un fichier. Les données sont des données binaires brutes, stockées en interne str
. Je vais écrire par le biais d'un codage utf-8 codec. Cependant, je reçois UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 25: character maps to <undefined>
dans le cp1252.py
fichier.
Cela me semble Python essaie d'interpréter les données à l'aide de la page de code par défaut. Mais il n'est pas ont une page de code par défaut. C'est pourquoi je suis en utilisant str
, pas unicode
.
Je pense que mes questions sont les suivantes:
- Comment puis-je représenter des données binaires brutes en mémoire, en Python?
- Quand je suis en train d'écrire des données binaires brutes par le biais d'un codec, comment puis-je encoder/unencode?
Vous dites que vous avez données brutes dans un str, comment allez-vous générer des données en premier lieu? Je suis en supposant que vous avez une unicode source quelque part, mais il n'est pas clair pour moi si vous écrivez "raw" unicode dans les str, ou, si vous lisez à partir d'un fichier (comme objet) ou... (Poster un exemple de chaîne qui illustre cette erreur serait utile!)
OriginalL'auteur Chris B. | 2010-04-09
Vous devez vous connecter pour publier un commentaire.
NOTE: ceci a été écrit pour Python 2.x. Vous ne savez pas si applicable 3.x.
Votre utilisation de
str
pour des données binaires brutes dans la mémoire est correcte.[Si vous utilisez la version 2.6 de Python+, il est même préférable d'utiliser
bytes
qui 2.6+ est juste un alias pourstr
mais exprime votre volonté de mieux, et vous aidera si un jour vous port le code Python 3.]Comme les autres, la note, l'écriture binaire des données grâce à un codec est étrange. Une écriture codec prend unicode et sorties octets dans le fichier. Vous essayez de le faire à l'envers, d'où notre confusion au sujet de vos intentions...
[Et votre diagnostic de l'erreur semble correct: depuis le codec attend unicode, Python est le décodage de votre str en unicode avec le système de codage par défaut, qui étouffe.]
Ce que vous voulez voir dans le fichier de sortie?
Si le fichier doit contenir les données binaires en tant que-est:
Alors vous ne devez pas envoyer à travers un codec; vous devez l'écrire
le fichier directement. Un codec code tout et ne peut
émettent valide les codages de caractères d'unicode (dans votre cas, UTF-8 valide).
Il n'y a pas d'entrée vous pouvez le donner à faire émettre arbitraire
les séquences d'octets!
devrait ouvrir le fichier directement, et mélanger écrit de
some_data
avec
some_text.encode('utf8')
...Noter, cependant, que le mélange de l'UTF-8 avec des données arbitraires est très
une mauvaise conception, parce que ces fichiers sont très difficiles à traiter
avec! Outils de comprendre unicode va s'étouffer sur le binaire
de données, vous laissant avec pas de moyen pratique pour la même vue (sans parler de l'
modifier) le fichier.
Si vous voulez un amical représentation de l'arbitraire d'octets dans
unicode:
Passer
data.encode('base64')
à la codec. Base64 ne produit quenettoyer ascii (lettres, chiffres, et un peu de ponctuation) de sorte qu'il
peut être clairement intégré dans quoi que ce soit, il semble clairement à des gens comme
des données binaires, et il est assez compact (un peu plus de 33%
les frais généraux).
P. S. vous pouvez noter que
data.encode('base64')
est étrange..encode()
est censé prendre unicode, mais je suis en train de donner unchaîne?! Python a plusieurs pseudo-codecs convertir str->str
telles que "base64" et "zlib".
.encode()
retourne toujours un str, mais vous allez nourrir dans un codecattend unicode?! Dans ce cas, il ne contiendra plus propre
ascii, donc il n'a pas d'importance. Vous pouvez écrire explicitement
data.encode('base64').encode('utf8')
si elle vous fait vous sentirmieux.
Si vous avez besoin d'un mappage 1:1 de l'arbitraire d'octets unicode:
Passer
data.decode('latin1')
à la codec.latin1
cartesoctets de 0 à 255 pour les caractères unicode de 0 à 255, ce qui est plutôt élégant.
Le codec, bien sûr, l'encodage de vos personnages - 128 à 255 sont
encodé sur 2 ou 3 octets en UTF-8 (étonnamment, la moyenne
les frais généraux est de 50%, plus de base64!). De ce fait, tue le
"l'élégance" d'avoir un mappage 1:1.
Note également que des caractères unicode 0-255 inclure méchant
invisible/les caractères de contrôle (saut de ligne, saut, doux trait d'union, etc.)
faire de vos données binaires ennuyeux à vue dans les éditeurs de texte.
Compte tenu de ces inconvénients, je ne recommande pas latin1 à moins que
vous comprenez exactement pourquoi vous le voulez.
Je suis juste de mentionner comme les autres "naturel" de codage des ressorts
à l'esprit.
OriginalL'auteur Beni Cherniavsky-Paskin
Pour votre première question: en Python, régulière des chaînes (c'est à dire, pas de chaînes unicode) sont des données binaires. Si vous souhaitez écrire les chaînes unicode et des données binaires, tourner les chaînes unicode en données binaires et les mettre ensemble:
Pour votre deuxième question: vous
write()
les données brutes; puis, quand vous le lisez, vous le faites comme ceci:Et de faire
yourFile.write(regular_string)
vous donne l'erreur? Vous n'avez pas besoin de plus d'encoder un régulier de la chaîne, comme je l'ai dit, c'est déjà cru octets.Faites-vous quelque chose de stupide comme l'utilisation de Python 3, peut-être?
Ce n'est pas Python 3. C'est un str, écrit par un utf-8 codec, qui est en quelque sorte interprétée par la cp1252 codec au cours de ce processus. Je soupçonne que Python s'attend à des chaînes unicode pour son codec, donc automatiquement traduit la str pour un objet unicode, ce qui provoque la conversion et de l'erreur. Je ne sais pas trop comment faire pour l'en empêcher, cependant.
Si vous avez des données binaires brutes stockées dans un str, vous ne voulez pas vous obtenir n'importe où près d'un codec. Il doit être écrit directement à un fichier ouvert en mode binaire. Je n'ai aucune idée de ce que tu veux dire en disant que vous avez des données binaires brutes enregistrées dans la mémoire interne au format utf-8. Qui n'a pas de sens.
OriginalL'auteur Daniel G
Vous ne devriez pas l'habitude d'utiliser des codecs
str
, sauf pour les transformer enunicode
s. Peut-être que vous devriez être à la recherche à l'aide de lalatin-1
codec si vous pensez que vous voulez "données brutes" dans votre unicodes.Alors pourquoi êtes-vous à l'aide d'un codec?
Je suis en train d'écrire des données binaires brutes dans un fichier texte, avec un certain nombre de chaînes unicode. Quand j'ai essayer d'écrire des données binaires brutes (que j'ai stockée en interne au format utf-8) pour un utf-8 codec, j'ai le cp1252 erreur.
Puis l'écrire directement dans le fichier, au lieu de passer par le codec.
OriginalL'auteur Ignacio Vazquez-Abrams