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:
<?xml encoding="utf-8"?>
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:
>>> x = eval("'Capit\\xc3\\xa1n\\n'")
>>> x
'Capit\xc3\xa1n\n'
>>> x[5]
'\xc3'
>>> len(x[5])
1
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:
>>> x.decode('utf-8')
u'Capit\xe1n\n'
Gregg Lind preguntó: Creo que faltan algunas piezas aquí: el archivo f2 contiene: hex:
0000000: 4361 7069 745c 7863 335c 7861 316e Capit\xc3\xa1n
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.