TLDR? Tratar:file = open(filename, encoding='cp437)
¿Por qué? Cuando uno usa:
file = open(filename)
text = file.read()
Python asume que el archivo usa la misma página de códigos que el entorno actual (cp1252 en el caso de la publicación de apertura) e intenta decodificarlo en su propio UTF-8 predeterminado. Si el archivo contiene caracteres de valores no definidos en esta página de códigos (como 0x90) obtenemos UnicodeDecodeError. A veces no conocemos la codificación del archivo, a veces la codificación del archivo puede ser manejada por Python (como, por ejemplo, cp790), a veces el archivo puede contener codificaciones mixtas.
Si dichos caracteres no son necesarios, uno puede decidir reemplazarlos por signos de interrogación, con:
file = open(filename, errors='replace')
Otra solución es usar:
file = open(filename, errors='ignore')
Los caracteres se dejan intactos, pero también se enmascararán otros errores.
Una solución bastante buena es especificar la codificación, pero no ninguna codificación (como cp1252), sino la que tiene TODOS los caracteres definidos (como cp437):
file = open(filename, encoding='cp437')
La página de códigos 437 es la codificación original de DOS. Todos los códigos están definidos, por lo que no hay errores al leer el archivo, no se ocultan errores, los caracteres se conservan (no se dejan intactos pero aún se distinguen).