¿Cómo convierto el formato de un archivo de Unicode a ASCII usando Python?

Utilizo una herramienta de terceros que genera un archivo en formato Unicode. Sin embargo, prefiero que esté en ASCII. La herramienta no tiene configuraciones para cambiar el formato de archivo.

¿Cuál es la mejor manera de convertir todo el formato de archivo usando Python?

Puede convertir el archivo fácilmente con la simple función de unicode , pero tendrá problemas con los caracteres Unicode sin un equivalente ASCII directo.

Este blog recomienda el módulo unicodedata , que parece ocuparse de convertir aproximadamente los caracteres sin valores ASCII correspondientes directos, por ejemplo,

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

normalmente se convierte a

 Klft skrms infr p fdral lectoral groe 

que está bastante mal. Sin embargo, al utilizar el módulo unicodedata , el resultado puede estar mucho más cerca del texto original:

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

Creo que este es un tema más profundo de lo que te das cuenta . Simplemente cambiar el archivo de Unicode a ASCII es fácil, sin embargo, conseguir que todos los caracteres de Unicode se traduzcan en equivalentes ASCII razonables (muchas letras no están disponibles en ambas codificaciones) es otra.

Este tutorial de Python Unicode puede darle una mejor idea de lo que sucede con las cadenas Unicode que se traducen a ASCII: http://www.reportlab.com/i18n/python_unicode_tutorial.html

Aquí hay una cita útil del sitio:

Python 1.6 también obtiene una función incorporada “Unicode”, a la que puede especificar la encoding:

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

Los tres de estos devuelven lo mismo, ya que los caracteres en “Hola” son comunes a las tres codificaciones.

Ahora vamos a codificar algo con un acento europeo, que está fuera de ASCII. Lo que vea en una consola puede depender de la configuración regional de su sistema operativo; Windows me permite escribir en ISO-Latin-1.

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

Si no puede escribir una letra e aguda, puede ingresar la cadena ‘Andr \ 202’, que es inequívoca.

Unicode es compatible con todas las operaciones comunes, como la iteración y la división. No los atropellaremos aquí.

Por cierto, este es un comando de Linux iconv para hacer este tipo de trabajo.

 iconv -f utf8 -t ascii output.txt 

Aquí hay un código simple (y estúpido) para hacer la traducción de la encoding. Supongo (pero no deberías) que el archivo de entrada está en UTF-16 (Windows lo llama simplemente ‘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))) 

Tenga en cuenta que esto no funcionará si hay caracteres en el archivo Unicode que no sean también caracteres ASCII. Puede hacer lo siguiente para convertir los caracteres no reconocidos en ‘?’:

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

Echa un vistazo a los documentos para opciones más simples. Si necesita hacer algo más sofisticado, puede consultar el Hammer UNICODE at the Python Cookbook.

Me gusta esto:

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

Sin embargo, tenga en cuenta que esto fallará con una excepción UnicodeDecodeError si hay caracteres que no se pueden convertir a ASCII.

EDITAR: Como Pete Karl acaba de señalar, no hay una asignación uno a uno de Unicode a ASCII. Por lo tanto, algunos caracteres simplemente no se pueden convertir de una manera que conserve la información. Además, el ASCII estándar es más o menos un subconjunto de UTF-8, por lo que realmente no es necesario descodificarlo.

Para mi problema en el que solo quería omitir los caracteres que no son ASCII y solo dar salida a ASCII, la siguiente solución funcionó muy bien:

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

Es importante tener en cuenta que no hay un formato de archivo ‘Unicode’. Unicode puede codificarse a bytes de varias maneras diferentes. Más comúnmente UTF-8 o UTF-16. Necesitará saber cuál es la herramienta de terceros que está generando. Una vez que lo sabes, la conversión entre diferentes codificaciones es bastante fácil:

 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() 

Como se señaló en las otras respuestas, probablemente querrá proporcionar un controlador de errores al método de encoding. Usar ‘reemplazar’ como controlador de errores es simple, pero modificará su texto si contiene caracteres que no pueden representarse en ASCII.

Como han señalado otros carteles, ASCII es un subconjunto de Unicode.

Sin embargo, si usted:

  • tener una aplicación legada
  • no controlas el código de esa aplicación
  • está seguro de que su entrada cae en el subconjunto ASCII

Entonces el siguiente ejemplo muestra cómo hacerlo:

 mystring = u'bar' type(mystring)  myasciistring = (mystring.encode('ASCII')) type(myasciistring)