2009-05-27 20 views
7

Puede alguien explicarme esta cosa extraña:Unicode de Python en la terminal del OS X

Cuando en Python Shell escribo la siguiente cadena cirílico:

>>> print 'абвгд' 
абвгд 

pero cuando escribo:

>>> print u'абвгд' 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-9: ordinal not in range(128) 

Dado que el primer tring salió correctamente, creo que mi terminal OS X puede representar unicode, pero resulta que no puede en el segundo caso. Por qué ?

Respuesta

16
>>> print 'абвгд' 
абвгд 

Cuando escribe algunos caracteres, su terminal decide cómo se representan estos caracteres a la aplicación. Su terminal podría dar los caracteres a la aplicación codificada como utf-8, ISO-8859-5 o incluso algo que solo su terminal entiende. Python obtiene estos caracteres como una secuencia de bytes. Luego, Python imprime estos bytes tal como están, y su terminal los interpreta de alguna manera para mostrar los caracteres. Desde su terminal por lo general interpreta los bytes de la misma manera, ya que les codificada antes, todo lo que se muestra como las ha escrito en.

>>> u'абвгд' 

Aquí se escribe en algunos personajes que llegan al intérprete de Python como una secuencia de bytes, tal vez codificado de alguna manera por la terminal. Con el prefijo u, python intenta convertir estos datos a unicode. Para hacer esto correctamente, python debe saber qué codificación usa su terminal. En su caso, parece que Python adivina que la codificación de sus terminales sería ASCII, pero los datos recibidos no coinciden, por lo que obtiene un error de codificación.

La forma recta hacia adelante para crear cadenas Unicode en una sesión interactiva por lo tanto sería algo como esto esto:

>>> us = 'абвгд'.decode('my-terminal-encoding') 

En los archivos también puede especificar la codificación del archivo con una línea de modo especial:

# -*- encoding: ISO-8859-5 -*- 
us = u'абвгд' 

Para conocer otras formas de configurar la codificación de entrada predeterminada, puede consultar sys.setdefaultencoding(...) o sys.stdin.encoding.

+0

Sí, esto tiene mucho sentido para mí, gracias. – disc0dancer

+0

+1 respuesta muy completa –

0

Un objeto Unicode debe codificarse antes de poder mostrarse en algunas consolas. Trate

u'абвгд'.encode() 

lugar para codificar el Unicode a un objeto de cadena (lo más probable usando UTF-8 como codificación predeterminada, pero depende de su configuración pitón)

+0

esto no está funcionando - encode() lanza el mismo error. – disc0dancer

3

También, asegúrese de que la codificación del terminal se establece a Unicode/UTF-8 (y no ASCII, lo que parece ser su entorno):

http://www.rift.dk/news.php?item.7.6

+0

Me lo figuré, pero lo que me molesta es que mi terminal SÍ muestra unicode correctamente si está tipeado como una cadena normal - p. 'уникоде', pero arroja un error si trato de imprimir la misma cadena como u'уникоде ' – disc0dancer

9

Además de asegurar su terminal OS X se establece en UTF-8, es posible que desee establecer su pitón por defecto sys codificación a UTF-8 o mejor. Cree un archivo en /Library/Python/2.5/site-packages llamado sitecustomize.py. En este archivo puso:

import sys 
sys.setdefaultencoding('utf-8') 

setdefaultencoding El método está disponible sólo por el módulo de sitio, y se retira de la sys namespace once startup has completed. Como tal, deberá iniciar un nuevo intérprete de Python para que el cambio surta efecto. Puede verificar la codificación predeterminada actual en cualquier momento después del inicio con sys.getdefaultencoding().

Si los personajes no son ya Unicode y hay que convertirlos, utilice el método decode en una cadena con el fin de decodificar el texto de algún otro juego de caracteres Unicode en ... mejor para especificar qué conjunto de caracteres:

s = 'абвгд'.decode('some_cyrillic_charset') # makes the string unicode 
print s.encode('utf-8') # transform the unicode into utf-8, then print it 
+0

Esto resolvió mis problemas, aunque la explicación de repr() no es correcta. Cometí un error en mi pregunta (perdón) que ahora corregí: estaba imprimiendo la cadena u'абвгд 'en realidad, así que no es un error repr(). De hecho, no obtengo el error si omito la instrucción de impresión, solo obtengo u '\ xd0 \ xb0 \ xd0 \ xb1 \ xd0 \ xb2 \ xd0 \ xb3 \ xd0 \ xb4' Mi conjetura sería que la codificación predeterminada - mac-roman es de alguna manera capaz de representar caracteres cyrilic (que, por otro lado, no tiene sentido ...), pero no es cirílico en Unicode. Realmente no entiendo esto :) – disc0dancer

+0

Gracias por la información discodancer ... tienes razón ... es malo. –

+0

No cambie la codificación predeterminada del sistema; arregla tus valores Unicode en su lugar. Cambiar la codificación predeterminada puede romper las bibliotecas que dependen del, * comportamiento predeterminado *. Hay una razón por la que tiene que forzar la recarga de un módulo antes de poder hacer esto. –

0

'абвгд' no es una cadena Unicode

u'абвгд' es una cadena Unicode

No puede imprimir cadenas Unicode sin codificarlos. Cuando trabaje con cadenas en su aplicación, quiere asegurarse de que cualquier entrada sea decodificada y cualquier salida codificada. De esta forma, su aplicación solo tratará cadenas de caracteres unicode internamente y cadenas de salida en UTF8.

Como referencia:

>>> 'абвгд'.decode('utf8') == u'абвгд' 
>>> True 
13

A partir de Python 2.6, puede utilizar la variable de entorno PYTHONIOENCODING para decirle a Python que el terminal es capaz UTF-8. La manera más fácil de hacer esto es permanente añadiendo la siguiente línea a su ~/.bash_profile:

export PYTHONIOENCODING=utf-8 

Terminal.app showing unicode output from Python

+0

¡Gracias, hecho mi día! – bouke

+0

Buen ejemplo, especialmente teniendo en cuenta que la construcción de OSX python viene con el escaso 'sys.maxunicode == 0xffff' –

+0

Tuve un problema con sympy pretty print y tu truco resolvió el problema. Gracias. – Pouya

Cuestiones relacionadas