¿Por qué declarar Unicode por cadena en Python?

Todavía estoy aprendiendo python y tengo una duda:

En Python 2.6.x normalmente declaro la encoding en el encabezado del archivo de esta manera (como en PEP 0263 )

# -*- coding: utf-8 -*- 

Después de eso, mis cadenas se escriben como de costumbre:

 a = "A normal string without declared Unicode" 

Pero cada vez que veo un código de proyecto de python, la encoding no se declara en el encabezado. En su lugar, se declara en cada cadena como esta:

 a = u"A string with declared Unicode" 

¿Cual es la diferencia? ¿Cuál es el propósito de esto? Sé que Python 2.6.x establece la encoding ASCII de forma predeterminada, pero la statement del encabezado la puede anular, así que, ¿cuál es el punto de la statement por cadena?

Addendum: Parece que he mezclado la encoding de archivos con la encoding de cadenas. Gracias por explicarlo 🙂

Esas son dos cosas diferentes, como han mencionado otros.

Cuando especifica # -*- coding: utf-8 -*- , le está diciendo a Python que el archivo fuente que ha guardado es utf-8 . El valor predeterminado para Python 2 es ASCII (para Python 3 es utf-8 ). Esto solo afecta a cómo el intérprete lee los caracteres en el archivo.

En general, probablemente no sea la mejor idea incrustar caracteres Unicode altos en su archivo sin importar cuál sea la encoding; puede utilizar cadenas de escape de Unicode, que funcionan en cualquiera de las dos codificaciones.


Cuando declara una cadena con una u al frente , como u'This is a string' , le dice al comstackdor de Python que la cadena es Unicode, no bytes. Esto es manejado en su mayoría de forma transparente por el intérprete; la diferencia más obvia es que ahora puede incrustar caracteres Unicode en la cadena (es decir, u'\u2665' ahora es legal). Puede utilizar from __future__ import unicode_literals para que sea el predeterminado.

Esto solo se aplica a Python 2; en Python 3, el valor predeterminado es Unicode, y debe especificar una b al frente (como b'These are bytes' , para declarar una secuencia de bytes).

Como han dicho otros, # coding: especifica la encoding en la que se guarda el archivo fuente. Aquí hay algunos ejemplos para ilustrar esto:

Un archivo guardado en el disco como cp437 (encoding de mi consola), pero sin encoding declarada

 b = 'über' u = u'über' print b,repr(b) print u,repr(u) 

Salida:

  File "C:\ex.py", line 1 SyntaxError: Non-ASCII character '\x81' in file C:\ex.py on line 1, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details 

Salida de archivo con # coding: cp437 agregado:

 über '\x81ber' über u'\xfcber' 

Al principio, Python no sabía la encoding y se quejó del carácter no ASCII. Una vez que conoció la encoding, la cadena de bytes obtuvo los bytes que estaban realmente en el disco. Para la cadena Unicode, Python leyó \ x81, lo sabía en cp437 que era un ü , y lo decodificó en el punto de código Unicode para ü que es U + 00FC. Cuando se imprimió la cadena de bytes, Python envió el valor hexadecimal 81 a la consola directamente. Cuando se imprimió la cadena Unicode, Python detectó correctamente la encoding de mi consola como cp437 y tradujo Unicode ü al valor de cp437 para ü .

Esto es lo que sucede con un archivo declarado y guardado en UTF-8:

 ├╝ber '\xc3\xbcber' über u'\xfcber' 

En UTF-8, ü se codifica como los bytes hexadecimales C3 BC , por lo que la cadena de bytes contiene esos bytes, pero la cadena Unicode es idéntica al primer ejemplo. Python leyó los dos bytes y los decodificó correctamente. Python imprimió la cadena de bytes incorrectamente, porque envió los dos bytes UTF-8 que representan ü directamente a mi consola cp437.

Aquí el archivo se declara cp437, pero se guarda en UTF-8:

 ├╝ber '\xc3\xbcber' ├╝ber u'\u251c\u255dber' 

La cadena de bytes todavía obtuvo los bytes en el disco (UTF-8 hexadecimal bytes C3 BC ), pero los interpretó como dos caracteres cp437 en lugar de un solo carácter codificado en UTF-8. Esos dos caracteres fueron traducidos a puntos de código Unicode, y todo se imprime incorrectamente.

Eso no establece el formato de la cadena; Establece el formato del archivo. Incluso con ese encabezado, "hello" es una cadena de bytes, no una cadena Unicode. Para hacerlo Unicode, tendrás que usar u"hello" todas partes. El encabezado es solo una sugerencia de qué formato usar al leer el archivo .py .

La definición del encabezado es definir la encoding del código en sí, no las cadenas resultantes en tiempo de ejecución.

colocar un carácter no-ascii como en el script de python sin la definición del encabezado utf-8 generará un error de advertencia http://sofes.miximages.com/encoding/www.freeimagehosting.net

Hice el siguiente módulo llamado Unicoder para poder realizar la transformación en variables:

 import sys import os def ustr(string): string = 'u"%s"'%string with open('_unicoder.py', 'w') as script: script.write('# -*- coding: utf-8 -*-\n') script.write('_ustr = %s'%string) import _unicoder value = _unicoder._ustr del _unicoder del sys.modules['_unicoder'] os.system('del _unicoder.py') os.system('del _unicoder.pyc') return value 

Luego en tu progtwig puedes hacer lo siguiente:

 # -*- coding: utf-8 -*- from unicoder import ustr txt = 'Hello, Unicode World' txt = ustr(txt) print type(txt) #