Tengo algunos problemas cerebrales para entender leer y escribir texto en un archivo (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'
Así que escribo en Capit\xc3\xa1n
mi editor favorito, en el archivo f2.
Luego:
>>> 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é no estoy entendiendo aquí? Claramente, me falta algo de magia vital (o buen sentido). ¿Qué escribe uno en archivos de texto para obtener conversiones adecuadas?
Lo que realmente no puedo entender aquí es cuál es el punto de la representación UTF-8, si no puedes hacer que Python lo reconozca, cuando viene del exterior. ¡Tal vez debería simplemente JSON volcar la cadena y usarla en su lugar, ya que tiene una representación sorprendente! Más concretamente, ¿hay una representación ASCII de este objeto Unicode que Python reconocerá y decodificará al ingresar desde un archivo? Si es así, ¿cómo lo consigo?
>>> print simplejson.dumps(ss)
'"Capit\u00e1n"'
>>> print >> file('f3','w'), simplejson.dumps(ss)
>>> simplejson.load(open('f3'))
u'Capit\xe1n'
u'\xe1'
es un punto de código UnicodeU+00e1
que se puede representar usando 1 o más bytes dependiendo de la codificación de caracteres (es 2 bytes en utf-8).b'\xe1'
es un byte (un número 225), la letra que puede representar depende de la codificación de caracteres utilizada para decodificarla, por ejemplo, esб
(U+0431
) en cp1251,с
(U+0441
) en cp866, etc.En lugar de meterse con los métodos de codificación y decodificación, me resulta más fácil especificar la codificación al abrir el archivo. El
io
módulo (agregado en Python 2.6) proporciona unio.open
función, que tiene un parámetro de codificación.Use el método abierto del
io
módulo.Luego, después de llamar a la función read () de f, se devuelve un objeto Unicode codificado.
Tenga en cuenta que en Python 3, la
io.open
función es un alias para laopen
función incorporada. La función abierta incorporada solo admite el argumento de codificación en Python 3, no Python 2.Editar: Anteriormente, esta respuesta recomendaba el módulo de códecs . El módulo de códecs puede causar problemas al mezclar
read()
yreadline()
, por lo tanto, esta respuesta ahora recomienda módulo io .Use el método abierto del módulo de códecs.
Luego, después de llamar a la función read () de f, se devuelve un objeto Unicode codificado.
Si conoce la codificación de un archivo, usar el paquete de códecs será mucho menos confuso.
Ver http://docs.python.org/library/codecs.html#codecs.open
fuente
open(file,'w')
hacerlocodecs.open(file,'w','utf-8')
resueltocodecs.open(...)
método también se ajusta completamente alwith open(...):
estilo, donde sewith
preocupa por cerrar el archivo después de todo? Parece funcionar de todos modos.with codecs.open(...) as f:
todo el tiempo.Ahora todo lo que necesitas en Python3 es
open(Filename, 'r', encoding='utf-8')
[Editar el 10/02/2016 para la aclaración solicitada]
Python3 agregó el parámetro de codificación a su función abierta. La siguiente información sobre la función abierta se recopila desde aquí: https://docs.python.org/3/library/functions.html#open
Entonces, al agregar
encoding='utf-8'
como parámetro a la función abierta, la lectura y escritura del archivo se realiza como utf8 (que ahora también es la codificación predeterminada de todo lo que se hace en Python).fuente
codecs.open('somefile', encoding='utf-8')
stackoverflow.com/a/147756/149428Entonces, he encontrado una solución para lo que estoy buscando, que es:
Hay algunos códecs inusuales que son útiles aquí. Esta lectura particular le permite a uno tomar representaciones UTF-8 desde Python, copiarlas en un archivo ASCII y hacer que se lean en Unicode. Bajo la decodificación "string-escape", las barras no se duplicarán.
Esto permite el tipo de viaje de ida y vuelta que estaba imaginando.
fuente
(codecs.open(file,"r","utf-8")
y, de manera simple,open(file,"r").read().decode("utf-8")
ambas funcionaron perfectamente.fuente
En realidad, esto funcionó para mí para leer un archivo con codificación UTF-8 en Python 3.2:
fuente
Para leer en una cadena Unicode y luego enviar a HTML, hice esto:
Útil para servidores http con tecnología python.
fuente
Te has topado con el problema general de las codificaciones: ¿cómo puedo saber en qué codificación está un archivo?
Respuesta: No puede, a menos que el formato de archivo lo permita . XML, por ejemplo, comienza con:
Este encabezado se eligió cuidadosamente para que pueda leerse sin importar la codificación. En su caso, no existe tal pista, por lo tanto, ni su editor ni Python tienen idea de lo que está sucediendo. Por lo tanto, debe usar el
codecs
módulo y usarcodecs.open(path,mode,encoding)
que proporciona el bit que falta en Python.En cuanto a su editor, debe verificar si ofrece alguna forma de configurar la codificación de un archivo.
El objetivo de UTF-8 es poder codificar caracteres de 21 bits (Unicode) como un flujo de datos de 8 bits (porque eso es lo único que todas las computadoras del mundo pueden manejar). Pero como la mayoría de los sistemas operativos son anteriores a la era Unicode, no tienen herramientas adecuadas para adjuntar la información de codificación a los archivos en el disco duro.
El siguiente problema es la representación en Python. Esto se explica perfectamente en el comentario de heikogerlach . Debe comprender que su consola solo puede mostrar ASCII. Para mostrar Unicode o cualquier cosa> = charcode 128, debe usar algún medio de escape. En su editor, no debe escribir la cadena de visualización escapada sino lo que significa la cadena (en este caso, debe ingresar la diéresis y guardar el archivo).
Dicho esto, puede usar la función Python eval () para convertir una cadena escapada en una cadena:
Como puede ver, la cadena "\ xc3" se ha convertido en un solo carácter. Esta es ahora una cadena de 8 bits, codificada en UTF-8. Para obtener Unicode:
Gregg Lind preguntó: Creo que faltan algunas piezas aquí: el archivo f2 contiene: hex:
codecs.open('f2','rb', 'utf-8')
, por ejemplo, los lee en caracteres separados (esperado) ¿Hay alguna forma de escribir en un archivo en ASCII que funcione?Respuesta: Eso depende de lo que quieras decir. ASCII no puede representar caracteres> 127. Por lo tanto, necesita alguna forma de decir "los siguientes caracteres significan algo especial", que es lo que hace la secuencia "\ x". Dice: Los siguientes dos caracteres son el código de un solo carácter. "\ u" hace lo mismo con cuatro caracteres para codificar Unicode hasta 0xFFFF (65535).
Por lo tanto, no puede escribir directamente Unicode en ASCII (porque ASCII simplemente no contiene los mismos caracteres). Puede escribirlo como escapes de cadena (como en f2); en este caso, el archivo se puede representar como ASCII. O puede escribirlo como UTF-8, en cuyo caso, necesita una transmisión segura de 8 bits.
Su solución usando
decode('string-escape')
funciona, pero debe saber cuánta memoria usa: tres veces la cantidad de usocodecs.open()
.Recuerde que un archivo es solo una secuencia de bytes con 8 bits. Ni los bits ni los bytes tienen un significado. Eres tú quien dice "65 significa 'A'". Como
\xc3\xa1
debería convertirse en "à" pero la computadora no tiene medios para saberlo, debe indicarlo especificando la codificación que se usó al escribir el archivo.fuente
a excepción de
codecs.open()
, uno puede usario.open()
para trabajar con Python2 o Python3 para leer / escribir archivos Unicodeejemplo
fuente
with io.open('data.txt', 'w', 'utf-8') as file:
y da un error:TypeError: an integer is required
. Después me cambiéwith io.open('data.txt', 'w', encoding='utf-8') as file:
y funcionó.Bueno, su editor de texto favorito no se da cuenta de que
\xc3\xa1
se supone que son literales de caracteres, pero los interpreta como texto. Es por eso que obtienes las barras invertidas dobles en la última línea: ahora es una barra invertida +xc3
, etc. real en tu archivo.Si desea leer y escribir archivos codificados en Python, mejor utilice el módulo de códecs .
Pegar texto entre el terminal y las aplicaciones es difícil, porque no sabes qué programa interpretará tu texto usando qué codificación. Puedes probar lo siguiente:
Luego pegue esta cadena en su editor y asegúrese de que la almacena usando Latin-1. Bajo el supuesto de que el portapapeles no distorsiona la cuerda, el viaje de ida y vuelta debería funcionar.
fuente
La secuencia \ x .. es algo específico de Python. No es una secuencia de escape de bytes universal.
La forma en que ingrese realmente en un código no ASCII codificado en UTF-8 depende de su sistema operativo y / o su editor. Así es como lo haces en Windows . Para que OS X ingrese a con un acento agudo, puede presionar option+ Ey luego A, y casi todos los editores de texto en OS X admiten UTF-8.
fuente
También puede mejorar la
open()
función original para trabajar con archivos Unicode reemplazándola en su lugar, utilizando lapartial
función. La belleza de esta solución es que no necesita cambiar ningún código antiguo. Es transparentefuente
Estaba tratando de analizar iCal usando Python 2.7.9:
Pero estaba obteniendo:
y se solucionó con solo:
(Ahora puede imprimir liké á böss).
fuente
Encontré el enfoque más simple cambiando la codificación predeterminada de todo el script para que sea 'UTF-8':
ninguna
open
,print
u otra declaración que acaba utilizaráutf8
.Funciona al menos para
Python 2.7.9
.Thx va a https://markhneedham.com/blog/2015/05/21/python-unicodeencodeerror-ascii-codec-cant-encode-character-uxfc-in-position-11-ordinal-not-in-range128/ ( mira al final).
fuente