2012-08-16 20 views
5

Al parecer, no puedo hacer eso en Python 2.7:cadena literal de bytes con caracteres no ASCII

value = '國華' 

Parece Python está utilizando una codificación para codificar los caracteres de la cadena literal a una cadena de bytes. ¿Qué es esa codificación? ¿Es esa la codificación definida en sys.getdefaultencoding(), la codificación del archivo fuente, o algo más?

Gracias

+1

¿Está esa línea en el archivo fuente, o en la línea de comandos? Además, ¿de verdad quieres aprender las complejidades de la codificación en Python 2.7 (que es ligeramente diferente de 2.6 y 3.x), o simplemente estás tratando de solucionar un problema que podría resolverse colocando un 'u' antes ¿Las citas? – abarnert

+0

En realidad estoy tratando de aprender las complejidades de la codificación en Python 2.7. Y esto está en un archivo fuente, pero también me interesa saber si eso es diferente en un símbolo del sistema. – Flavien

+1

Python 2.7 dice que no debe hacer esto, pero si está interesado en qué hace CPython 2.7 si lo hace de todos modos ... los bytes literales dentro de las comillas en el archivo fuente (por ejemplo, '\ xe5 \ x9c \ x8b \ xe8 \ x8f \ xaf ') se almacenan como una cadena de bytes. Dado que la declaración de codificación del archivo fuente puede no ser la misma que 'sys.getdefaultencoding()', puede que no haya forma de interpretarla con seguridad, pero los bytes están ahí. Y si las dos codificaciones son las mismas, al igual que la del terminal, y esa codificación puede manejar esos caracteres, incluso puede "imprimir valor" y ver lo que espera. Es eso lo que quieres, o hay más? – abarnert

Respuesta

7

getdefaultencoding no tiene relación con la codificación del archivo de origen o el terminal. Es la codificación utilizada para convertir cadenas de bytes implícitamente en cadenas Unicode y siempre debe ser 'ascii' en Python 2.X ('utf8' en Python 3.X).

En Python 2.x, su línea de código en un script sin codificación declarada produce un error:

SyntaxError: Non-ASCII character '\x87' in file ... 

El carácter real no ASCII puede variar, pero no funcionará sin una codificación declaración. Una declaración de codificación es requiere para usar caracteres que no sean ASCII en Python 2.X. La declaración de codificación debe coincidir con la codificación del archivo de origen. Por ejemplo:

# coding: utf8 
value = '國華' 

cuando se guarda como cp936 produce:

SyntaxError: 'utf8' codec can't decode byte 0x87 in position 9: invalid start byte 

Cuando la codificación es correcta, los bytes de la cadena de bytes son, literalmente, lo que está en el archivo de origen, por lo que contendrá el codificada bytes de los personajes. Cuando Python analiza una cadena Unicode, los bytes se decodifican utilizando la codificación de origen declarada a Unicode. Nótese la diferencia cuando se imprime una cadena de bytes UTF-8 y una cadena Unicode en una consola cp936:

# coding: utf8 
value = '國華' 
print value,repr(value) 
value = u'國華' 
print value,repr(value) 

Salida:

鍦嬭彲 '\xe5\x9c\x8b\xe8\x8f\xaf' 
國華 u'\u570b\u83ef' 

La cadena de bytes contiene los 3 bytes UTF-8 codificaciones del dos caracteres, pero se muestran incorrectamente ya que la secuencia de bytes no es entendida por un terminal cp936. Unicode se imprime correctamente y la cadena contiene los puntos de código Unicode decodificados de los bytes UTF-8 del archivo de origen.

nota la diferencia cuando se declara y el uso de la codificación que coincida con el terminal:

# coding: cp936 
value = '國華' 
print value,repr(value) 
value = u'國華' 
print value,repr(value) 

Salida:

國華 '\x87\xf8\xc8A' 
國華 u'\u570b\u83ef' 

El contenido de la cadena de bytes es ahora el codificaciones de 2 bytes cp936 del dos caracteres ('A' equivalente a '\ x41') y se muestra correctamente ya que el terminal entiende la secuencia de bytes cp936. La cadena Unicode contiene los mismos puntos de código Unicode para los dos caracteres que en el ejemplo anterior porque la secuencia de bytes de origen se decodificó utilizando la codificación de origen declarada para Unicode.

Si una secuencia de comandos tiene una correcta declaración de codificación fuente y utiliza cadenas Unicode para el texto, se mostrará los caracteres correctos independientemente de la codificación de la terminal 2 . Lanzará un UnicodeEncodeError si el terminal no admite el caracter en lugar de mostrar el caracter incorrecto.

Nota final: Python 2.X se predetermina a la codificación 'ascii' a menos que se indique lo contrario y permite caracteres que no sean ASCII en cadenas de bytes si la codificación los admite. Python 3.X se predetermina a la codificación 'utf8' (así que asegúrese de guardar en esa codificación o declare lo contrario), y no permiten caracteres que no sean ASCII en cadenas de bytes.

Si la fuente del terminal admite el carácter.
Si la codificación del terminal es compatible con el carácter.

1
value = b'國華' 

no tiene sentido (la b está implícito en Python 2.x) - ¿Por qué quieres un cadena de bytes que contiene caracteres? Python simplemente reproduce los bytes en cualquier codificación que use su terminal/editor. Lo que queremos es un personaje cadena:

value = u'國華' 

En un archivo de código fuente (en contraposición a un shell interactivo), no se olvide de declare the encoding añadiendo la siguiente línea al principio del archivo:

# -*- coding: utf-8 -*- 
+0

Bueno, aparentemente, los diseñadores de Python no pensaron que no tenía sentido ya que lo hicieron válido. Realmente no respondiste mi pregunta, qué codificación utiliza Python cuando ejecuto esa línea, ¿cómo puedo averiguarlo? – Flavien

+0

Cuando ejecuta esa línea en el shell interactivo, o en un archivo de origen con una declaración de codificación, o ... ¿qué? – abarnert

+2

@Flavien caracteres no ASCII en literales de bytes son un artefacto histórico. No hay un código que los haga válidos, simplemente se aceptan accidentalmente, y eso se remonta a la época en que Python no tenía una semántica clara de cadenas de bytes vs. caracteres. Los caracteres no ASCII en literales de bytes ya no son válidos; se han eliminado [de Python 3] (http://ideone.com/f1iLN). Python no usa ninguna codificación cuando ejecuta esa línea. El archivo es una cadena de bytes, y también lo es el valor del objeto de bytes que produce el literal. – phihag

Cuestiones relacionadas