2009-12-30 16 views
9

Estaba mirando este question y comencé a preguntarme qué hace realmente el print.¿Qué función funciona en realidad python print()?

Nunca he descubierto cómo usar string.decode() y string.encode() para obtener una cadena unicode "out" en el shell interactivo de python en el mismo formato que la versión impresa. No importa lo que hago, me sale bien

  1. UnicodeEncodeError o
  2. la cadena escapada con la notación "\ x ##" ...

Ésta es Python 2.x, pero estoy ya tratar de arreglar mis caminos y de hecho llamar print() :)

Ejemplo:

>>> import sys 
>>> a = '\xAA\xBB\xCC' 
>>> print(a) 
ª»Ì 
>>> a.encode(sys.stdout.encoding) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in ? 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xaa in position 0: ordinal not in range(128) 
>>> a.decode(sys.stdout.encoding) 
u'\xaa\xbb\xcc' 

EDITAR:

¿Por qué estoy preguntando esto? Estoy harto y cansado de los errores encode() y me di cuenta de que desde print puedo hacerlo (al menos en el shell interactivo). Yo sé que el debe haber una manera de hacer mágicamente la codificación CORRECTAMENTE, cavando la información de qué codificación a usar de alguna parte ...

INFORMACIÓN ADICIONAL: estoy corriendo Python 2.4.3 (# 1, 3 sep 2009, 15:37:12) [GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] en linux2

>>> sys.stdin.encoding 
'ISO-8859-1' 
>>> sys.stdout.encoding 
'ISO-8859-1' 

Sin embargo, los resultados son los mismos con Python 2.6. 2 (r262: 71600, 8 de septiembre de 2009, 13:06:43) en la misma caja de Linux.

+2

Podría darnos un ejemplo de lo que ha intentado, lo que quería/esperaba conseguir, y lo que tienes? Nos ayudaría a ayudarte mejor. –

+2

¿La pregunta está relacionada con Python 2 o 3? –

+0

Dado que él habla sobre "función de impresión", es probable que sea Python 3. –

Respuesta

9

EDIT: (cambios importantes entre esta edición y la anterior ... NOTA:. Estoy usando Python 2.6.4 en una caja de Ubuntu)

primer lugar, en mi primer intento de respuesta , Proporcioné información general sobre print y str que voy a dejar a continuación para el beneficio de que alguien tenga problemas más simples con print y dude sobre esta pregunta. En cuanto a un nuevo intento de lidiar con el problema experimentado por el OP ... Básicamente, me inclino a decir que no hay una bala de plata aquí y si print de alguna manera logra dar sentido a un literal de cadena extraño, entonces ese no es un comportamiento reproducible . Me llevaron a esta conclusión por la siguiente interacción divertida con Python en mi ventana de terminal:

>>> print '\xaa\xbb\xcc' 
�� 

has necesitado entrada ª »I directamente desde el terminal? En una terminal de Linux usando UTF-8 como la codificación, esto es en realidad por lectura como seis bytes, que luego se pueden hacer para parecerse a tres caracteres Unicode con la ayuda del método decode:

>>> 'ª»Ì' 
'\xc2\xaa\xc2\xbb\xc3\x8c' 
>>> 'ª»Ì'.decode(sys.stdin.encoding) 
u'\xaa\xbb\xcc' 

Por lo tanto, la '\xaa\xbb\xcc' literal solo tiene sentido si decodifica como un literal de latin-1 (bueno, en realidad podría usar una codificación diferente que concuerde con latin-1 en los caracteres relevantes). En cuanto a print 'solo funciona' en su caso, ciertamente no es para mí, como se mencionó anteriormente.

Esto se explica por el hecho de que cuando se utiliza una cadena literal no prefijado con una u - es decir, en lugar de "asdf"u"asdf" - la cadena resultante usará parte de codificación no Unicode. No; como cuestión de hecho, el objeto de cadena en sí va a ser de codificación, no consciente, y tendrá que tratarlo como si estuviera codificado con codificación x, para el valor correcto de x. Esta idea básica me lleva a la siguiente:

a = '\xAA\xBB\xCC' 
a.decode('latin1') 
# result: u'\xAA\xBB\xCC' 
print(a.decode('latin1')) 
# output: ª»Ì 

nota la falta de errores de decodificación y la salida apropiada (que espero ser adecuada permanecer en cualquier otro cuadro). Aparentemente, Python puede dar sentido a su literal de cadena, pero no sin cierta ayuda.

¿Le sirve de ayuda? (Por lo menos en la comprensión de cómo funcionan las cosas, si no en hacer el manejo de las codificaciones más fácil ...)


Ahora, para algunos bits divertidas con algún valor explicativo (con suerte)! Esto funciona muy bien para mí:

sys.stdout.write("\xAA\xBB\xCC".decode('latin1').encode(sys.stdout.encoding)) 

Saltarse ya sea la decodificación o la parte de resultados codificar en una excepción relacionada con Unicode. En teoría, esto tiene sentido, ya que la primera decodificación es necesaria para decidir qué caracteres hay en la cadena dada (lo único obvio a primera vista es qué bytes hay - la idea de Python 3 de tener cadenas (unicode) para caracteres y bytes para, bueno, bytes, de repente parece magníficamente razonable), mientras que la codificación es necesaria para que la salida respete la codificación de la secuencia de salida. Ahora bien, este

sys.stdout.write("ąöî\n".decode(sys.stdin.encoding).encode(sys.stdout.encoding)) 

también funciona como se esperaba, pero los personajes son en realidad viene desde el teclado y también lo son en realidad codificado con la codificación de la entrada estándar ... Además,

ord('ą'.decode('utf-8').encode('latin2')) 

devuelve la correcta 177 (mi la codificación de entrada es utf-8), pero '\ xc4 \ x85'.encode (' latin2 ') no tiene sentido para Python, ya que no tiene idea de cómo dar sentido a' \ xc4 \ x85 'y se da cuenta de que intenta el código 'ascii' es lo mejor que puede hacer.


La respuesta original:

The relevant bit de documentación de Python (para la versión 2.6.4) dice que print(obj) está destinado a imprimir la cadena dada por str(obj). Supongo que podría envolverlo en una llamada al unicode (como en el unicode(str(obj))) para obtener una cadena Unicode, o simplemente podría usar Python 3 e intercambiar esta molestia en particular por un par de diferentes. ;-)

Por cierto, esto demuestra que se puede manipular el resultado de print ing un objeto al igual que se puede manipular el resultado de llamar str en un objeto, es decir, por jugar con el método __str__. Ejemplo:

class Foo(object): 
    def __str__(self): 
     return "I'm a Foo!" 

print Foo() 

En cuanto a la aplicación real de print, espero que esto no va a ser útil en absoluto, pero si realmente quiere saber lo que está pasando ... Es en el archivo en el Python/bltinmodule.c Fuentes de Python (estoy viendo la versión 2.6.4). Busque una línea que comienza con builtin_print. En realidad es completamente sencillo, no hay magia pasando allí.:-)

Esperemos que esto responda a su pregunta ... Pero si tiene un problema más arcano que me falta por completo, comente, voy a hacer un segundo intento. Además, supongo que estamos lidiando con Python 2.x; de lo contrario, supongo que no tendré un comentario útil.

+0

Desafortunadamente el builtin_print no está en ese archivo en 2.4 http://svn.python.org/view/python/branches/release24-maint/Python/bltinmodule.c?view=markup – Kimvais

+0

Supongo que es porque en ese entonces , 'print' seguía siendo la sintaxis, mientras que' builtin_print' es necesario para que funcione como una función. Además, al decodificar cadenas provenientes de stdin, querrás usar 'sys.stdin.encoding' en lugar de' sys. stdout.encoding' - aunque en la caja típica de hoy en día, con toda probabilidad, son lo mismo. –

+0

Um, supongo que solo espero aclarar lo que sucede debajo del capó con la última enmienda a la respuesta - en cuanto a qué se puede hacer para evitar problemas de codificación, supongo que no es muy optimista. De todos modos, me pregunto si aclara algo ... Y luego está mi nuevo comentario adjunto a la pregunta en sí. Definitivamente estoy empezando a compartir en el "académico interés "involucrado aquí. (Estoy agregando esto a etiquetas interesantes, por cierto; ;-)) –

5

print() usa sys.stdout.encoding para determinar qué puede entender la consola de salida y luego utiliza esta codificación en la llamada al str.encode().

[EDIT] Si look at the source, se pone sys.stdout y luego llama:

PyFile_WriteObject(PyTuple_GetItem(args, i), file, 
       Py_PRINT_RAW); 

supongo que la magia está en Py_PRINT_RAW pero the source sólo dice:

if (flags & Py_PRINT_RAW) { 
    value = PyObject_Str(v); 
    } 

Así que hay magia aquí. Un bucle sobre los argumentos con sys.stdout.write(str(item)) debería hacer el truco.

+0

+1 para aclarar la sutileza importante que me perdí por completo en mi respuesta. –

+0

Si bien esto es probablemente correcto, no parece responder a mi pregunta. Aparentemente, print() finalmente llama a sys.stdout.write() que hace algo de magia porque el código de la cadena de caracteres (sys.stdout.encoding) falla ... – Kimvais

+2

@Kimvais: busqué la fuente. Sin magia –

2
>>> import sys 
>>> a = '\xAA\xBB\xCC' 
>>> print(a) 
ª»Ì 

Todo print está haciendo aquí es escribir prima bytes-sys.stdout. La cadena a es una cadena de bytes, no caracteres Unicode.

¿Por qué estoy preguntando esto? Estoy harto y cansado de los errores de encode() y me di cuenta de que la impresión puede hacerlo (al menos en el shell interactivo). Sé que la debe haber una manera de hacer arte de magia la codificación de manera suficiente, en la excavación de la información lo que la codificación a utilizar de alguna parte ...

Ay no, print está haciendo nada en absoluto mágica aquí. Le das algunos bytes, vacia los bytes a stdout.

Para usar .encode() y .decode() correctamente, debe comprender la diferencia entre los bytes y los caracteres, y me temo que debe averiguar la codificación correcta que debe usar.

0
import sys 

source_file_encoding = 'latin-1' # if there is no -*- coding: ... -*- line 

a = '\xaa\xbb\xcc' # raw bytes that represent string in source_file_encoding 

# print bytes, my terminal tries to interpret it as 'utf-8' 
sys.stdout.write(a+'\n') 
# -> �� 

ua = a.decode(source_file_encoding) 
sys.stdout.write(ua.encode(sys.stdout.encoding)+'\n') 
# -> ª»Ì 

Ver Defining Python Source Code Encodings

Cuestiones relacionadas