Question

J'utilise un outil tiers qui génère un fichier au format Unicode. Cependant, je préfère que ce soit en ASCII. L'outil ne dispose pas de paramètres pour modifier le format de fichier.

Quel est le meilleur moyen de convertir le format de fichier entier à l'aide de Python?

Était-ce utile?

La solution

Vous pouvez convertir le fichier assez facilement en utilisant la fonction unicode , mais vous rencontrerez des problèmes avec les caractères Unicode sans équivalent ASCII direct.

Ce blog recommande le unicodedata module, qui semble prendre en charge la conversion approximative des caractères sans transfert direct valeurs ASCII correspondantes, par exemple

>>> title = u"Klüft skräms inför på fédéral électoral große"

est généralement converti en

Klft skrms infr p fdral lectoral groe

ce qui est assez faux. Cependant, en utilisant le module unicodedata , le résultat peut être beaucoup plus proche du texte d'origine:

>>> import unicodedata
>>> unicodedata.normalize('NFKD', title).encode('ascii','ignore')
'Kluft skrams infor pa federal electoral groe'

Autres conseils

Je pense que le problème est plus profond que vous ne le réalisez . Changer simplement le fichier d'Unicode en ASCII est facile, cependant, convertir tous les caractères Unicode en des équivalents ASCII raisonnables (de nombreuses lettres ne sont pas disponibles dans les deux encodages) en est un autre.

Ce didacticiel Python Unicode peut vous donner une meilleure idée de ce qu'il advient des chaînes Unicode traduites en ASCII: http://www.reportlab.com/i18n/python_unicode_tutorial.html

Voici une citation utile du site:

  

Python 1.6 obtient également un "unicode"   fonction intégrée, à laquelle vous pouvez   spécifiez le codage:

> >>> unicode('hello') u'hello'
> >>> unicode('hello', 'ascii') u'hello'
> >>> unicode('hello', 'iso-8859-1') u'hello'
> >>>
  

Tous les trois retournent le même   chose, puisque les personnages dans 'Bonjour'   sont communs aux trois encodages.

     

Maintenant encodons quelque chose avec un   Accent européen, qui est en dehors de   ASCII. Ce que vous voyez sur une console peut   dépend de votre système d'exploitation   lieu; Windows me permet de taper   ISO-Latin-1.

> >>> a = unicode('André','latin-1')
> >>> a u'Andr\202'
  

Si vous ne pouvez pas taper une lettre aiguë e,   vous pouvez entrer la chaîne 'Andr \ 202',   ce qui est sans ambiguïté.

     

Unicode supporte tous les courants   des opérations telles que l'itération et   scission. Nous ne les verrons pas   ici.

À propos, il s'agit d'une commande linux iconv pour effectuer ce type de travail.

iconv -f utf8 -t ascii <input.txt >output.txt

Voici un code simple (et stupide) permettant d’encoder la traduction. Je suppose (mais vous ne devriez pas) que le fichier d'entrée est en UTF-16 (Windows appelle cela simplement 'Unicode').

input_codec = 'UTF-16'
output_codec = 'ASCII'

unicode_file = open('filename')
unicode_data = unicode_file.read().decode(input_codec)
ascii_file = open('new filename', 'w')
ascii_file.write(unicode_data.write(unicode_data.encode(output_codec)))

Notez que cela ne fonctionnera pas si le fichier Unicode contient des caractères qui ne sont pas également des caractères ASCII. Vous pouvez effectuer les opérations suivantes pour transformer des caractères non reconnus en '?':

ascii_file.write(unicode_data.write(unicode_data.encode(output_codec, 'replace')))

Découvrez la documentation pour des choix plus simples. Si vous avez besoin de faire quelque chose de plus sophistiqué, vous pouvez consulter le marteau UNICODE à l'adresse le livre de recettes Python.

Comme ceci:

uc = open(filename).read().decode('utf8')
ascii = uc.decode('ascii')

Notez cependant que cela échouera avec une exception UnicodeDecodeError s'il existe des caractères qui ne peuvent pas être convertis en ASCII.

EDIT: Comme Pete Karl vient de le dire, il n’existe pas de correspondance individuelle entre Unicode et ASCII. Ainsi, certains caractères ne peuvent tout simplement pas être convertis de manière à préserver les informations. De plus, l'ASCII standard est plus ou moins un sous-ensemble de l'UTF-8, vous n'avez donc même pas besoin de décoder.

Pour mon problème où je voulais juste ignorer les caractères non-ascii et ne sortir que la sortie ascii, la solution ci-dessous a très bien fonctionné:

    import unicodedata
    input = open(filename).read().decode('UTF-16')
    output = unicodedata.normalize('NFKD', input).encode('ASCII', 'ignore')

Il est important de noter qu’il n’existe pas de format de fichier «Unicode». Unicode peut être codé en octets de différentes manières. Le plus souvent UTF-8 ou UTF-16. Vous aurez besoin de savoir lequel de votre outil tiers produit en sortie. Une fois que vous savez cela, la conversion entre différents encodages est assez facile:

in_file = open("myfile.txt", "rb")
out_file = open("mynewfile.txt", "wb")

in_byte_string = in_file.read()
unicode_string = bytestring.decode('UTF-16')
out_byte_string = unicode_string.encode('ASCII')

out_file.write(out_byte_string)
out_file.close()

Comme indiqué dans les autres réponses, vous souhaiterez probablement fournir un gestionnaire d'erreurs à la méthode d'encodage. Utiliser 'remplacer' comme gestionnaire d'erreurs est simple, mais modifiera votre texte s'il contient des caractères qui ne peuvent pas être représentés en ASCII.

Comme d'autres afficheurs l'ont noté, ASCII est un sous-ensemble d'Unicode.

Cependant si vous:

  • avoir une application héritée
  • vous ne contrôlez pas le code de cette application
  • vous êtes certain que votre entrée tombe dans le sous-ensemble ASCII

Ensuite, l'exemple ci-dessous montre comment procéder:

mystring = u'bar'
type(mystring)
    <type 'unicode'>

myasciistring = (mystring.encode('ASCII'))
type(myasciistring)
    <type 'str'>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top