Convertir archivo a Ascii es lanzar excepciones

Como resultado de mi pregunta anterior , he codificado esto:

def ConvertFileToAscii(args, filePath): try: # Firstly, make sure that the file is writable by all, otherwise we can't update it os.chmod(filePath, 0o666) with open(filePath, "rb") as file: contentOfFile = file.read() unicodeData = contentOfFile.decode("utf-8") asciiData = unicodeData.encode("ascii", "ignore") asciiData = unicodedata.normalize('NFKD', unicodeData).encode('ASCII', 'ignore') temporaryFile = tempfile.NamedTemporaryFile(mode='wt', delete=False) temporaryFileName = temporaryFile.name with open(temporaryFileName, 'wb') as file: file.write(asciiData) if ((args.info) or (args.diagnostics)): print(filePath + ' converted to ASCII and stored in ' + temporaryFileName) return temporaryFileName # except KeyboardInterrupt: raise except Exception as e: print('!!!!!!!!!!!!!!!\nException while trying to convert ' + filePath + ' to ASCII') print(e) exc_type, exc_value, exc_traceback = sys.exc_info() print(traceback.format_exception(exc_type, exc_value, exc_traceback)) if args.break_on_error: sys.exit('Break on error\n') 

Cuando lo ejecuto, obtengo excepciones como esta:

 ['Traceback (most recent call last): ', ' File "/home/ker4hi/tools/xmlExpand/xmlExpand.py", line 99, in ConvertFileToAscii unicodeData = contentOfFile.decode("utf-8") ', "UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf6 in position 1081: invalid start byte"] 

¿Qué estoy haciendo mal?

Realmente no me importa la pérdida de datos convirtiéndolos a ASCII.

ox9C es Ü una U con una marca diacrítica (Umlaut), puedo vivir sin ella.

¿Cómo puedo convertir estos archivos para que contengan solo los caracteres puros de Ascii? ¿Realmente necesito abrirlos como binario y comprobar cada byte?

Utilizar:

 contentOfFile.decode('utf-8', 'ignore') 

La excepción es de la fase de deencoding , donde no ignoró el error.

0x00f6 está codificado en ö (ouml) en ISO-8859-1 . Supongo que está utilizando el decodificador Unicode incorrecto.

Pruebe: unicodeData = contentOfFile.decode("ISO-8859-1")

No es necesario cargar todo el archivo en la memoria y llamar a .decode() en él. open() tiene un parámetro de encoding (use io.open() en Python 2):

 with open(filename, encoding='ascii', errors='ignore') as file: ascii_char = file.read(1) 

Si necesita una transliteración ASCII de texto Unicode; considerar unidecode

Realmente no me importa la pérdida de datos convirtiéndolos a ASCII. … ¿Cómo puedo convertir estos archivos para que contengan solo los caracteres puros de Ascii?

Una forma es usar la opción de reemplazo para el método de decode . La ventaja de reemplazar sobre ignorar es que obtiene marcadores de posición para los valores faltantes, lo que me ayuda a evitar una mala interpretación del texto.

Asegúrese de utilizar la encoding ASCII en lugar de UTF-8. De lo contrario, puede perder caracteres ascii adyacentes cuando el decodificador intente volver a sincronizarse.

Por último, ejecute encode('ascii') después del paso de deencoding. De lo contrario, te quedas con una cadena Unicode en lugar de una cadena de bytes.

 >>> string_of_unknown_encoding = 'L\u00f6wis'.encode('latin-1') >>> now_in_unicode = string_of_unknown_encoding.decode('ascii', 'replace') >>> back_to_bytes = now_in_unicode.replace('\ufffd', '?').encode('ascii') >>> type(back_to_bytes)  >>> print(back_to_bytes) b'L?wis' 

Dicho esto, TheRightWay ™ para hacer esto es comenzar a preocuparse por la pérdida de datos y usar la encoding correcta (claramente su entrada no está en UTF-8, de lo contrario la desencoding no habría fallado):

 >>> string_of_known_latin1_encoding = 'L\u00f6wis'.encode('latin-1') >>> now_in_unicode = string_of_known_latin1_encoding.decode('latin-1') >>> back_to_bytes = now_in_unicode.encode('ascii', 'replace') >>> type(back_to_bytes)  >>> print(back_to_bytes)