Écrire du texte Unicode dans un fichier texte?

je suis en train de retirer des données D'un Google doc, de les traiter, et de les écrire dans un fichier (que je finirai par coller dans une page Wordpress).

il a quelques symboles non-ASCII. Comment puis-je les convertir en toute sécurité en Symboles qui peuvent être utilisés dans HTML source?

actuellement je suis en train de tout convertir en Unicode sur le chemin de l'entrée, en le joignant tous ensemble dans une chaîne de Python, puis en faisant:

import codecs
f = codecs.open('out.txt', mode="w", encoding="iso-8859-1")
f.write(all_html.encode("iso-8859-1", "replace"))

il y a une erreur d'encodage la dernière ligne:

UnicodeDecodeError:' ascii ' codec ne peut pas décoder byte 0xa0 en position 12286: ordinal pas in range(128)

solution partielle:

ce Python tourne sans erreur:

row = [unicode(x.strip()) if x is not None else u'' for x in row]
all_html = row[0] + "<br/>" + row[1]
f = open('out.txt', 'w')
f.write(all_html.encode("utf-8")

mais alors si j'ouvre le fichier texte réel, je vois beaucoup de symboles comme:

Qur’an 

peut-être que je dois écrire à quelque chose d'autre qu'un fichier texte?

192
demandé sur Aaron Hall 2011-05-18 20:39:46

7 réponses

traite exclusivement avec les objets unicode autant que possible en décodant les choses aux objets unicode quand vous les obtenez et en les encodant si nécessaire sur le chemin de sortie.

si votre chaîne de caractères est en fait un objet unicode, vous devrez la convertir en un objet Unicode avant de l'écrire dans un fichier:

foo = u'Δ, Й, ק, ‎ م, ๗, あ, 叶, 葉, and 말.'
f = open('test', 'w')
f.write(foo.encode('utf8'))
f.close()

quand vous relirez ce fichier, vous obtiendrez une chaîne encodée en unicode que vous pourrez décoder en un objet unicode.:

f = file('test', 'r')
print f.read().decode('utf8')
285
répondu quasistoic 2011-05-18 16:49:01

en Python 2.6+, vous pouvez utiliser io.open() qui est par défaut ( builtin open() ) sur Python 3:

import io

with io.open(filename, 'w', encoding=character_encoding) as file:
    file.write(unicode_text)

il pourrait être plus pratique si vous devez écrire le texte progressivement (vous n'avez pas besoin d'appeler unicode_text.encode(character_encoding) plusieurs fois). Contrairement au module codecs , le module io est doté d'un support universel approprié.

51
répondu jfs 2016-01-29 13:49:08

le fichier ouvert par codecs.open est un fichier qui prend les données unicode , Les code dans iso-8859-1 et les écrit dans le fichier. Cependant, ce que vous essayez d'écrire n'est pas unicode ; vous prenez unicode et l'encodez dans iso-8859-1 vous-même . C'est ce que fait la méthode unicode.encode , et le résultat de l'encodage d'une chaîne unicode est un bytestring (un type str .)

vous devez soit utiliser normal open() et encoder l'unicode vous-même, ou (habituellement une meilleure idée) utilisez codecs.open() et pas encodez les données vous-même.

18
répondu Thomas Wouters 2011-05-18 16:55:20

Préface: votre visionneuse de travail?

assurez-vous que votre visualiseur/éditeur/terminal (quelle que soit la façon dont vous interagissez avec votre fichier encodé utf-8) peut lire le fichier. C'est souvent un problème sur Windows , par exemple, Bloc-notes.

écrire du texte Unicode dans un fichier texte?

en Python 2, Utilisez open du module io (c'est le même que le module builtin open en Python 3):

import io

meilleure pratique, en général, utilisez UTF-8 pour écrire aux fichiers (nous n'avons même pas à nous soucier de byte-order avec utf-8).

encoding = 'utf-8'

utf-8 est l'encodage le plus moderne et universellement utilisable - il fonctionne dans tous les navigateurs web, la plupart des éditeurs de texte (voir vos paramètres si vous avez des problèmes) et la plupart des terminaux/shells.

sur Windows, vous pouvez essayer utf-16le si vous êtes limité à regarder la sortie dans le bloc-notes (ou un autre spectateur limité).

encoding = 'utf-16le' # sorry, Windows users... :(

Et il suffit de l'ouvrir avec le gestionnaire de contexte et d'écrire des caractères unicode:

with io.open(filename, 'w', encoding=encoding) as f:
    f.write(unicode_object)

exemple utilisant de nombreux caractères Unicode

voici un exemple qui tente de cartographier tous les caractères possibles jusqu'à trois bits de large (4 est le max, mais ce serait aller un peu loin) de la représentation numérique (en nombres entiers) à un sortie imprimable encodée, avec son nom, si possible (mettez-le dans un fichier appelé uni.py ):

from __future__ import print_function
import io
from unicodedata import name, category
from curses.ascii import controlnames
from collections import Counter

try: # use these if Python 2
    unicode_chr, range = unichr, xrange
except NameError: # Python 3
    unicode_chr = chr

exclude_categories = set(('Co', 'Cn'))
counts = Counter()
control_names = dict(enumerate(controlnames))
with io.open('unidata', 'w', encoding='utf-8') as f:
    for x in range((2**8)**3): 
        try:
            char = unicode_chr(x)
        except ValueError:
            continue # can't map to unicode, try next x
        cat = category(char)
        counts.update((cat,))
        if cat in exclude_categories:
            continue # get rid of noise & greatly shorten result file
        try:
            uname = name(char)
        except ValueError: # probably control character, don't use actual
            uname = control_names.get(x, '')
            f.write(u'{0:>6x} {1}    {2}\n'.format(x, cat, uname))
        else:
            f.write(u'{0:>6x} {1}  {2}  {3}\n'.format(x, cat, char, uname))
# may as well describe the types we logged.
for cat, count in counts.items():
    print('{0} chars of category, {1}'.format(count, cat))

Cela doit exécuter dans l'ordre d'environ une minute, et vous pouvez visualiser le fichier de données, et si votre fichier viewer pouvez afficher unicode, vous le verrez. Des informations sur les catégories peuvent être trouvées ici . En se basant sur les comptes, nous pouvons probablement améliorer nos résultats en excluant les catégories Cn et Co, qui n'ont pas de symboles associés. avec eux.

$ python uni.py

il affichera le mapping hexadécimal, la catégorie , le symbole (à moins que ne peut pas obtenir le nom, donc probablement un caractère de contrôle), et le nom du symbole. par exemple

je recommande less sur Unix ou Cygwin (ne pas imprimer/cat le fichier entier à votre sortie):

$ less unidata

par exemple affichera similaire aux lignes suivantes que j'ai échantillonnées à partir de lui en utilisant Python 2 (unicode 5.2):

     0 Cc NUL
    20 Zs     SPACE
    21 Po  !  EXCLAMATION MARK
    b6 So  ¶  PILCROW SIGN
    d0 Lu  Ð  LATIN CAPITAL LETTER ETH
   e59 Nd  ๙  THAI DIGIT NINE
  2887 So  ⢇  BRAILLE PATTERN DOTS-1238
  bc13 Lo  밓  HANGUL SYLLABLE MIH
  ffeb Sm  →  HALFWIDTH RIGHTWARDS ARROW

mon Python 3.5 D'Anaconda a unicode 8.0, je présume que la plupart des 3 le feraient.

13
répondu Aaron Hall 2017-06-27 12:21:54
La manipulation des chaînes Unicode

est standardisée en Python 3.

  1. Char sont stockées dans Unicode
  2. vous n'avez besoin d'ouvrir le fichier qu'en utf-8

    out1 = "(嘉南大圳 ㄐㄧㄚ ㄋㄢˊ ㄉㄚˋ ㄗㄨㄣˋ )"
    fobj = open("t1.txt", "w", encoding="utf-8")
    fobj.write(out1)
    fobj.close()
    
8
répondu david m lee 2017-10-15 01:20:47

comment imprimer des caractères unicode dans un fichier:

enregistrez ceci dans le fichier: foo.py:

#!/usr/bin/python -tt
# -*- coding: utf-8 -*-
import codecs
import sys 
UTF8Writer = codecs.getwriter('utf8')
sys.stdout = UTF8Writer(sys.stdout)
print(u'e with obfuscation: é')

exécutez-le et sortie de la pipe à fichier:

python foo.py > tmp.txt

ouvert tmp.txt et regarder à l'intérieur, vous voyez ceci:

el@apollo:~$ cat tmp.txt 
e with obfuscation: é

ainsi vous avez enregistré unicode e avec une marque d'obfuscation sur elle à un fichier.

3
répondu Eric Leschinski 2013-12-27 18:36:02

cette erreur se produit lorsque vous essayez d'encoder une chaîne non-unicode: elle essaie de la décoder, en supposant qu'elle est en ASCII. Il y a deux possibilités:

  1. vous l'encodez en bytestring, mais parce que vous avez utilisé des codecs.open, la méthode write attend un objet unicode. Donc tu l'encodes, et il essaye de le décoder à nouveau. Essayez plutôt f.write(all_html) .
  2. all_html n'est pas, en fait, un objet unicode. Quand vous faites .encode(...) , il essaie d'abord de le décoder.
1
répondu Thomas K 2011-05-18 16:45:01