Jump to content

problema comparacion caracteres en python


Recommended Posts

Hola

 

requiero de la grandisima fuente de sabiduria que hay en chilecomparte para hacerles una consulta. estoy programando algo en python y por cosas del destino tengo que leer un archivo de texto en python y comparar si las cadenas son iguales.

 

por ejemplo supongamos un archivo de texto con nombre text.txt y que contiene la palabra montaña entonces yo hago algo como

archivo=open("text.txt")
for linea in archivo: 
       if linea=="montaña":
              print "algo"
       else:
             print linea+" montaña"

esto ultimo solo para ver la diferencia entre las palabras y me aparece el sgte error:

 

SyntaxError: Non-ASCII character '\xc3' in file C:\Users\ColdZeven\Desktop\1.py on line 5, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

 

al poner la linea #encoding: utf-8 al inicio del codigo (o puesta la codificacion de otras formas)

entra al else y me dice

 

monta±a monta├▒a

 

alguien me podria dar una manito para como hacer que compare correctamente?

 

saludos y muchas gracias =)

 

Link to comment
Share on other sites

[hide]

Aunque te parezca raro, lo que muestra en pantalla es correcto ("monta±a" y "monta├▒a"). El problema es que tu código fuente usa una codificación distinta a la que usa por defecto el símbolo de sistema de Windows. Normalmente el símbolo de sistema usa codificación OEM (en el mundo occidental, esto significa alguna codificación ASCII extendida, en los Windows en español debería ser CP850).

En el primer caso ("monta±a"), el código fuente está en Windows-1252, pero el símbolo de lo muestra como si fuese CP850; mientras que en el segundo caso ("monta├▒a"), el código fuente está en UTF-8, pero lo muestra como si fuese CP850.

Ahora, para solucionar el problema de cómo se representan los caracteres en pantalla (símbolo de sistema), hay que hacer 2 cosas:

  • Usar una fuente que admita Unicode (en otras palabras, no usar una fuente mapa de bits o raster)
  • Hacer que la página de códigos activa coincida con la codificación de tu código fuente
Para seleccionar una fuente que pueda representar caracteres Unicode en el símbolo de sistema:

 

Paso 1:

cmd1.png

 

Paso 2: en este caso yo elegí la fuente Lucida Console

cmd2.png

 

 

Ahora, en Windows, Python tiene problemas para mostrar caracteres en UTF-8 (mira este enlace)

cmd3.png

o sea, funciona a medias. Creo que es capaz de imprimir hasta la primera cadena que contenga caracteres especiales (> 127) y después tira error (IOError: [Errno 0] Error).

 

Así que la solución que estaría quedando sería usar la codificación Windows-1252.

En el símbolo de sistema ingresa el comando chcp 1252, con esto le indicas que use la codificación Windows-1252:

cmd4f18.png

Ojo, se supone que el archivo de texto que estás leyendo (text.txt) está codificado en ANSI (Windows-1252).

cmd5.png

 

Así que tu código fuente debería verse así (también tienes que guardarlo como ANSI, que es la opción por defecto en el bloc de notas):

# coding=windows-1252

archivo=open("text.txt")
for linea in archivo: 
       if linea=="montaña":
              print "algo"
       else:
             print linea+" montaña"

Si de todas formas quieres probar usando UTF-8 (se supone que el código fuente y el archivo de texto están en UTF-8), ingresa el comando chcp 65001 en el símbolo de sistema y después ejecutas tu script Python.

[/hide]

:huasonto:

Link to comment
Share on other sites

[hide]

Aunque te parezca raro, lo que muestra en pantalla es correcto ("monta±a" y "monta├▒a"). El problema es que tu código fuente usa una codificación distinta a la que usa por defecto el símbolo de sistema de Windows. Normalmente el símbolo de sistema usa codificación OEM (en el mundo occidental, esto significa alguna codificación ASCII extendida, en los Windows en español debería ser CP850).

En el primer caso ("monta±a"), el código fuente está en Windows-1252, pero el símbolo de lo muestra como si fuese CP850; mientras que en el segundo caso ("monta├▒a"), el código fuente está en UTF-8, pero lo muestra como si fuese CP850.

Ahora, para solucionar el problema de cómo se representan los caracteres en pantalla (símbolo de sistema), hay que hacer 2 cosas:

  • Usar una fuente que admita Unicode (en otras palabras, no usar una fuente mapa de bits o raster)
  • Hacer que la página de códigos activa coincida con la codificación de tu código fuente
Para seleccionar una fuente que pueda representar caracteres Unicode en el símbolo de sistema:

 

Paso 1:

cmd1.png

 

Paso 2: en este caso yo elegí la fuente Lucida Console

cmd2.png

 

 

Ahora, en Windows, Python tiene problemas para mostrar caracteres en UTF-8 (mira este enlace)

cmd3.png

o sea, funciona a medias. Creo que es capaz de imprimir hasta la primera cadena que contenga caracteres especiales (> 127) y después tira error (IOError: [Errno 0] Error).

 

Así que la solución que estaría quedando sería usar la codificación Windows-1252.

En el símbolo de sistema ingresa el comando chcp 1252, con esto le indicas que use la codificación Windows-1252:

cmd4f18.png

Ojo, se supone que el archivo de texto que estás leyendo (text.txt) está codificado en ANSI (Windows-1252).

cmd5.png

 

Así que tu código fuente debería verse así (también tienes que guardarlo como ANSI, que es la opción por defecto en el bloc de notas):

# coding=windows-1252

archivo=open("text.txt")
for linea in archivo: 
       if linea=="montaña":
              print "algo"
       else:
             print linea+" montaña"

Si de todas formas quieres probar usando UTF-8 (se supone que el código fuente y el archivo de texto están en UTF-8), ingresa el comando chcp 65001 en el símbolo de sistema y después ejecutas tu script Python.

[/hide]

:huasonto:

 

 

realice todo lo que dijiste, el problema es que tengo que usar si o si un archivo que esta en utf-8 (el que dice montaña) y la terminal me manda el siguiente error

 

LookupError: unknown encoding: cp65001

 

sino a veces me sale

print "asdf."

IOError: [Errno 2] No such file or directory

 

.sin embargo no estoy abriendo nada. sabes por que podria pasar esto?

Link to comment
Share on other sites

Actualizado :gua:

 

[hide]

Logré hacer que funcione en Python 2 con UTF-8 :huasonto:

 

Aquí hay algunas cosas que descubrí:

 

Python 2:

  • Hay que abrir el archivo usando codec.open para poder especificar la codificación de éste, pero con esto, el archivo se abre en modo binario, esto significa que los saltos de línea no se normalizan. O sea, al leer un archivo de texto guardado con el bloc de notas de Windows, tendrá líneas terminandas en "\r\n"
  • No reconoce la codificación UTF-8 en el símbolo de sistema de Windows (LookupError: unknown encoding: cp65001)
  • A pesar que se trabaje con UTF-8, hay que usar la página de códigos 850 en el símbolo de sistema de Windows (debido a lo anterior)
Python 3:
  • Sí reconoce la codificación UTF-8 en el símbolo de sistema de Windows (cp65001), al menos en la versión más reciente es así
  • Requiere que se use la página de códigos cp65001 (UTF-8) en el símbolo de sistema sólo si hay que imprimir caracteres que no se puedan representar con la página de códigos que esté usando actualmente el símbolo de sistema (que por defecto es cp850)
Ambas versiones normalizan los saltos de línea al abrir archivos en modo texto (todos quedan como "\n").

 

Ambas versiones realizan internamente una conversión si la codificación de la cadena que se va a imprimir no coincide con la página de códigos del símbolo de sistema. En este caso, la conversión sería UTF-8 a cp850 (UTF-8 = cp65001). Al parecer, esta conversión automática se realiza solamente si la codificación de origen es Unicode.

 

ACLARACIÓN: Al decir que cp850 es la página de códigos por defecto, me estoy refiriendo específicamente a Windows en español y en particular a la codificación que se usa en el símbolo de sistema de éste. Para otros sistemas operativos o idiomas, esto probablemente no sea así.

 

Se supone que el script y el archivo de texto (text.txt) están codificados en UTF-8.


Python 2

 

En Python 2 hay que usar codecs.open para poder especificar la codificación del archivo. Nótese el uso del prefijo u para las cadenas literales.

# coding=utf-8
import codecs

# El bloc de notas de Windows agrega un BOM a los archivos guardados en UTF-8.
# Para saltárselo, hay que usar 'utf-8-sig' en vez de 'utf-8'.
archivo = codecs.open("text.txt", encoding="utf_8_sig")

for linea in archivo:
	linea = linea.rstrip("\n\r")
	if linea == u"montaña":
		print u"<<< SE ENCONTRÓ >>>"
	else:
		print u"No hay montaña:\t" + linea
archivo.close()
No es necesario cambiar la fuente del símbolo de sistema. Además, no cambies la página de códigos, o sea, no ejecutes el comando chcp 65001 :no: .

 

NOTA: Ten en cuenta que dentro de tu script puedes usar cualquier caracter UTF-8 y, por ejemplo, ver si la cadena "αβγδ" se encuentra dentro del archivo de texto, pero no puedes imprimirla en pantalla porque esa cadena no es representable en la página de códigos cp850. O sea, el siguiente código sería válido y no daría problemas (ya que no imprime la cadena, sólo la busca dentro del archivo):

	if linea == u"αβγδ":
		print u"<<< SE ENCONTRÓ >>>"

Python 3

 

# coding=utf-8

# El bloc de notas de Windows agrega un BOM a los archivos guardados en UTF-8.
# Para saltárselo, hay que usar 'utf-8-sig' en vez de 'utf-8'.
archivo = open('text.txt', encoding='utf-8-sig', mode='rt')

for linea in archivo:
	linea = linea.rstrip('\n')
	if linea == "montaña":
		print("<<< SE ENCONTRÓ >>>")
	else:
		print("No hay montaña:\t", linea)

archivo.close()
Si vas a usar la página de códigos UTF-8 (usando el comando chcp 65001), entonces también tienes que cambiar la fuente del símbolo de sistema (Consolas o Lucida Console).

[/hide]

 

:huasonto:

Edited by susodicho
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...