J'ai des problèmes de cerveau dans la compréhension de la lecture et de l'écriture de texte dans un fichier (Python 2.4).
# The string, which has an a-acute in it.
ss = u'Capit\xe1n'
ss8 = ss.encode('utf8')
repr(ss), repr(ss8)
("u'Capit \ xe1n '", "' Capit \ xc3 \ xa1n '")
print ss, ss8
print >> open('f1','w'), ss8
>>> file('f1').read()
'Capit\xc3\xa1n\n'
Je tape donc Capit\xc3\xa1n
dans mon éditeur préféré, dans le fichier f2.
Ensuite:
>>> open('f1').read()
'Capit\xc3\xa1n\n'
>>> open('f2').read()
'Capit\\xc3\\xa1n\n'
>>> open('f1').read().decode('utf8')
u'Capit\xe1n\n'
>>> open('f2').read().decode('utf8')
u'Capit\\xc3\\xa1n\n'
Qu'est-ce que je ne comprends pas ici? De toute évidence, il me manque un peu de magie (ou de bon sens). Que faut-il taper dans des fichiers texte pour obtenir des conversions appropriées?
Ce que je ne parviens vraiment pas à comprendre ici, c'est à quoi sert la représentation UTF-8, si vous ne pouvez pas vraiment faire reconnaître Python, quand il vient de l'extérieur. Peut-être que je devrais simplement JSON vider la chaîne, et l'utiliser à la place, car cela a une représentation vérifiable! Plus précisément, existe-t-il une représentation ASCII de cet objet Unicode que Python reconnaîtra et décodera, en arrivant d'un fichier? Si oui, comment puis-je l'obtenir?
>>> print simplejson.dumps(ss)
'"Capit\u00e1n"'
>>> print >> file('f3','w'), simplejson.dumps(ss)
>>> simplejson.load(open('f3'))
u'Capit\xe1n'
u'\xe1'
est un point de code UnicodeU+00e1
qui peut être représenté en utilisant 1 ou plusieurs octets selon le codage des caractères (il est de 2 octets dans utf-8).b'\xe1'
est un octet (un nombre 225), quelle lettre s'il peut représenter dépend du codage de caractères utilisé pour le décoder, par exemple, il estб
(U+0431
) dans cp1251,с
(U+0441
) dans cp866, etc.Plutôt que de jouer avec les méthodes d'encodage et de décodage, je trouve plus facile de spécifier l'encodage lors de l'ouverture du fichier. Le
io
module (ajouté en Python 2.6) fournit uneio.open
fonction, qui a un paramètre de codage.Utilisez la méthode ouverte du
io
module.Ensuite, après avoir appelé la fonction read () de f, un objet Unicode codé est renvoyé.
Notez que dans Python 3, la
io.open
fonction est un alias pour laopen
fonction intégrée. La fonction ouverte intégrée ne prend en charge que l'argument de codage en Python 3, pas Python 2.Edit: Auparavant, cette réponse recommandait le module codecs . Le module codecs peut provoquer des problèmes lors du mixage
read()
etreadline()
, donc cette réponse recommande désormais le module io à la place.Utilisez la méthode ouverte du module codecs.
Ensuite, après avoir appelé la fonction read () de f, un objet Unicode codé est renvoyé.
Si vous connaissez l'encodage d'un fichier, l'utilisation du paquet de codecs va être beaucoup moins déroutante.
Voir http://docs.python.org/library/codecs.html#codecs.open
la source
open(file,'w')
lecodecs.open(file,'w','utf-8')
résoudrecodecs.open(...)
méthode est-elle également parfaitement conforme auwith open(...):
style, où lawith
fermeture du fichier se soucie après tout? Cela semble fonctionner de toute façon.with codecs.open(...) as f:
tout le temps.Maintenant, tout ce dont vous avez besoin en Python3 est
open(Filename, 'r', encoding='utf-8')
[Modifier le 2016-02-10 pour obtenir les clarifications demandées]
Python3 a ajouté le paramètre d' encodage à sa fonction ouverte. Les informations suivantes sur la fonction ouverte sont collectées à partir d'ici: https://docs.python.org/3/library/functions.html#open
Ainsi, en ajoutant
encoding='utf-8'
un paramètre à la fonction ouverte, la lecture et l'écriture du fichier se font toutes en utf8 (qui est également maintenant l'encodage par défaut de tout ce qui se fait en Python.)la source
codecs.open('somefile', encoding='utf-8')
stackoverflow.com/a/147756/149428J'ai donc trouvé une solution pour ce que je recherche, qui est:
Il existe des codecs inhabituels qui sont utiles ici. Cette lecture particulière permet de prendre des représentations UTF-8 depuis Python, de les copier dans un fichier ASCII et de les lire dans Unicode. Sous le décodage "string-escape", les barres obliques ne seront pas doublées.
Cela permet le type de voyage aller-retour que j'imaginais.
la source
(codecs.open(file,"r","utf-8")
et simplementopen(file,"r").read().decode("utf-8")
et les deux ont parfaitement fonctionné.la source
En fait, cela a fonctionné pour moi pour lire un fichier avec l'encodage UTF-8 en Python 3.2:
la source
Pour lire dans une chaîne Unicode puis envoyer au HTML, j'ai fait ceci:
Utile pour les serveurs http propulsés par python.
la source
Vous êtes tombé sur le problème général des encodages: comment savoir dans quel encodage se trouve un fichier?
Réponse: Vous ne pouvez pas sauf si le format de fichier le prévoit. XML, par exemple, commence par:
Cet en-tête a été soigneusement choisi afin qu'il puisse être lu quel que soit l'encodage. Dans votre cas, il n'y a pas un tel indice, donc ni votre éditeur ni Python n'ont la moindre idée de ce qui se passe. Par conséquent, vous devez utiliser le
codecs
module et utiliser celuicodecs.open(path,mode,encoding)
qui fournit le bit manquant en Python.Quant à votre éditeur, vous devez vérifier s'il offre un moyen de définir l'encodage d'un fichier.
L'utilité de l'UTF-8 est de pouvoir encoder des caractères 21 bits (Unicode) en tant que flux de données 8 bits (car c'est la seule chose que tous les ordinateurs du monde peuvent gérer). Mais comme la plupart des systèmes d'exploitation sont antérieurs à l'ère Unicode, ils ne disposent pas d'outils appropriés pour attacher les informations d'encodage aux fichiers sur le disque dur.
Le problème suivant est la représentation en Python. Ceci est parfaitement expliqué dans le commentaire de heikogerlach . Vous devez comprendre que votre console ne peut afficher que ASCII. Pour afficher Unicode ou quoi que ce soit> = charcode 128, il doit utiliser un moyen de s'échapper. Dans votre éditeur, vous ne devez pas taper la chaîne d'affichage échappée mais ce que signifie la chaîne (dans ce cas, vous devez saisir le tréma et enregistrer le fichier).
Cela dit, vous pouvez utiliser la fonction Python eval () pour transformer une chaîne échappée en chaîne:
Comme vous pouvez le voir, la chaîne "\ xc3" a été transformée en un seul caractère. Il s'agit maintenant d'une chaîne de 8 bits, encodée en UTF-8. Pour obtenir Unicode:
Gregg Lind a demandé: Je pense qu'il manque des morceaux ici: le fichier f2 contient: hex:
codecs.open('f2','rb', 'utf-8')
, par exemple, les lit tous dans des caractères séparés (attendu) Existe-t-il un moyen d'écrire dans un fichier en ASCII qui fonctionnerait?Réponse: Cela dépend de ce que vous voulez dire. ASCII ne peut pas représenter des caractères> 127. Il vous faut donc un moyen de dire "les prochains caractères signifient quelque chose de spécial", ce que fait la séquence "\ x". Il dit: Les deux caractères suivants sont le code d'un seul caractère. "\ u" fait de même en utilisant quatre caractères pour encoder Unicode jusqu'à 0xFFFF (65535).
Vous ne pouvez donc pas écrire directement Unicode en ASCII (car ASCII ne contient tout simplement pas les mêmes caractères). Vous pouvez l'écrire comme des échappements de chaîne (comme dans f2); dans ce cas, le fichier peut être représenté en ASCII. Ou vous pouvez l'écrire en UTF-8, auquel cas, vous avez besoin d'un flux sécurisé 8 bits.
Votre solution en utilisant
decode('string-escape')
fonctionne, mais vous devez être conscient de la quantité de mémoire que vous utilisez: trois fois la quantité d'utilisationcodecs.open()
.N'oubliez pas qu'un fichier n'est qu'une séquence d'octets de 8 bits. Ni les bits ni les octets n'ont de sens. C'est vous qui dites "65 signifie 'A'". Puisque
\xc3\xa1
devrait devenir "à" mais que l'ordinateur n'a aucun moyen de le savoir, vous devez le lui dire en précisant l'encodage qui a été utilisé lors de l'écriture du fichier.la source
sauf pour
codecs.open()
, on peut utiliserio.open()
pour travailler avec Python2 ou Python3 pour lire / écrire un fichier unicodeexemple
la source
with io.open('data.txt', 'w', 'utf-8') as file:
et a obtenu une erreur:TypeError: an integer is required
. Après avoir changé pourwith io.open('data.txt', 'w', encoding='utf-8') as file:
et cela a fonctionné.Eh bien, votre éditeur de texte préféré ne se rend pas compte qu'il
\xc3\xa1
s'agit de littéraux de caractères, mais il les interprète comme du texte. C'est pourquoi vous obtenez la double barre oblique inverse dans la dernière ligne - c'est maintenant une vraie barre oblique inversexc3
, etc. dans votre fichier.Si vous souhaitez lire et écrire des fichiers encodés en Python, utilisez au mieux le module codecs .
Coller du texte entre le terminal et les applications est difficile, car vous ne savez pas quel programme interprétera votre texte en utilisant quel encodage. Vous pouvez essayer ce qui suit:
Collez ensuite cette chaîne dans votre éditeur et assurez-vous qu'elle la stocke en utilisant Latin-1. Dans l'hypothèse où le presse-papiers ne brouille pas la chaîne, l'aller-retour devrait fonctionner.
la source
La séquence \ x .. est quelque chose de spécifique à Python. Ce n'est pas une séquence d'échappement d'octets universelle.
La façon dont vous entrez réellement dans le format non ASCII encodé en UTF-8 dépend de votre système d'exploitation et / ou de votre éditeur. Voici comment vous le faites dans Windows . Pour que OS X entre un avec un accent aigu, vous pouvez simplement appuyer sur option+ E, puis A, et presque tous les éditeurs de texte dans OS X prennent en charge UTF-8.
la source
Vous pouvez également améliorer la
open()
fonction d' origine pour travailler avec des fichiers Unicode en la remplaçant en place, à l'aide de lapartial
fonction. La beauté de cette solution est que vous n'avez pas besoin de modifier un ancien code. C'est transparent.la source
J'essayais d'analyser iCal en utilisant Python 2.7.9:
Mais je recevais:
et il a été corrigé avec juste:
(Maintenant, il peut imprimer liké á böss.)
la source
J'ai trouvé l'approche la plus simple en changeant l'encodage par défaut de l'ensemble du script pour être «UTF-8»:
tout
open
,print
ou toute autre déclaration sera simplement utiliserutf8
.Fonctionne au moins pour
Python 2.7.9
.Thx va à https://markhneedham.com/blog/2015/05/21/python-unicodeencodeerror-ascii-codec-cant-encode-character-uxfc-in-position-11-ordinal-not-in-range128/ ( regardez à la fin).
la source