Python Unicode Strings y el intérprete interactivo de Python

Estoy tratando de entender cómo Python 2.5 se ocupa de las cadenas Unicode. Aunque a estas alturas creo que tengo una buena idea de cómo se supone que debo manejarlos en el código, no comprendo por completo lo que sucede detrás de la escena, especialmente cuando escribe cadenas en el indicador del intérprete.

Por lo tanto, python pre 3.0 tiene dos tipos para cadenas, a saber: str (cadenas de bytes) y unicode , que se derivan de la basestring de basestring . El tipo predeterminado para cadenas es str .

str objetos str no tienen noción de su encoding real, son solo bytes. O bien, usted mismo ha codificado una cadena Unicode y, por lo tanto, sabe en qué encoding están, o ha leído un flujo de bytes cuya encoding también conoce (de manera indeal). Puede adivinar la encoding de una cadena de bytes cuya encoding es desconocida para usted, pero simplemente no existe una forma confiable de resolver esto. Lo mejor que puedes hacer es descodificar temprano, usar Unicode en todas partes de tu código y codificarlo tarde.

Esta bien. Pero, ¿las cadenas escritas en el intérprete sí están codificadas detrás de su espalda? Siempre que mi comprensión de las cadenas en Python sea correcta, ¿cuál es el método / configuración que utiliza python para tomar esta decisión?

La fuente de mi confusión son los diferentes resultados que obtengo cuando bash lo mismo en la instalación de Python de mi sistema y en la consola Python incrustada de mi editor.

  # Editor (Sublime Text) >>> s = "La caña de España" >>> s 'La ca\xc3\xb1a de Espa\xc3\xb1a' >>> s.decode("utf-8") u'La ca\xf1a de Espa\xf1a' >>> sys.getdefaultencoding() 'ascii' # Windows python interpreter >>> s= "La caña de España" >>> s 'La ca\xa4a de Espa\xa4a' >>> s.decode("utf-8") Traceback (most recent call last): File "", line 1, in  File "C:\Python25\lib\encodings\utf_8.py", line 16, in decode return codecs.utf_8_decode(input, errors, True) UnicodeDecodeError: 'utf8' codec can't decode byte 0xa4 in position 5: unexpected code byte >>> sys.getdefaultencoding() 'ascii' 

Permítame expandir la respuesta de Ignacio: en ambos casos hay una capa extra entre Python y usted: en un caso es Sublime Text y en la otra es cmd.exe . La diferencia en el comportamiento que se ve no se debe a Python sino a las diferentes codificaciones utilizadas por Sublime Text (utf-8, como parece) y cmd.exe (cp437).

Entonces, cuando '\xc3\xb1' ñ , Sublime Text envía '\xc3\xb1' a Python, mientras que cmd.exe envía \xa4 . [Estoy simplemente aquí, omitiendo detalles que no son relevantes para la pregunta].

Aun así, Python lo sabe. Desde cmd.exe probablemente obtendrá algo como:

 >>> import sys >>> sys.stdin.encoding 'cp437' 

mientras que dentro de Sublime Text obtendrás algo como

 >>> import sys >>> sys.stdin.encoding 'utf-8' 

El intérprete utiliza la encoding nativa del símbolo del sistema para la entrada de texto. En tu caso es CP437:

 >>> print '\xa4'.decode('cp437') ñ 

Te estás confundiendo porque el editor y el intérprete están usando diferentes codificaciones. El intérprete de Python usa el valor predeterminado de su sistema (en este caso, cp437 ), mientras que su editor usa utf-8 .

Tenga en cuenta que la diferencia desaparece si especifica una cadena Unicode, así:

 # Windows python interpreter >>> s = "La caña de España" >>> s 'La ca\xa4a de Espa\xa4a' >>> s = u"La caña de España" >>> s u'La ca\xf1a de Espa\xf1a' 

La moraleja de la historia? Las codificaciones son complicadas. Asegúrese de saber en qué encoding se encuentran los archivos de origen, o juegue de forma segura utilizando siempre la versión de escape de caracteres especiales.