python - type - ¿El mejor tipo de salida y prácticas de codificación para las funciones__repr__()?
python encoding ansi (3)
Últimamente, he tenido muchos problemas con __repr__()
, format()
y codificaciones. ¿Debería codificarse la salida de __repr__()
o ser una cadena unicode? ¿Hay una mejor codificación para el resultado de __repr__()
en Python? Lo que quiero mostrar tiene caracteres que no sean ASCII.
Uso Python 2.x y quiero escribir código que se pueda adaptar fácilmente a Python 3. El programa utiliza
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function # The ''Hello'' literal represents a Unicode object
Aquí hay algunos problemas adicionales que me han estado molestando, y estoy buscando una solución que los resuelva:
- La impresión en un terminal UTF-8 debería funcionar (he
sys.stdout.encoding
configurado enUTF-8
, pero sería mejor si otros casos funcionaran también). - Tubería de salida a un archivo (codificado en UTF-8) debería funcionar (en este caso,
sys.stdout.encoding
esNone
). - Mi código para muchas
__repr__()
actualmente tiene muchosreturn ….encode(''utf-8'')
, y eso es pesado. ¿Hay algo robusto y ligero? - En algunos casos, incluso tengo bestias feas como el
return (''<{}>''.format(repr(x).decode(''utf-8''))).encode(''utf-8'')
, es decir, la representación de objetos se decodifica, se pone en una cadena de formato y luego se vuelve a codificar. Me gustaría evitar tales transformaciones enrevesadas.
¿Qué recomendarías hacer para escribir __repr__()
simples __repr__()
que se comporten bien con respecto a estas preguntas de codificación?
Creo que un decorador puede manejar incompatibilidades __repr__
de una manera __repr__
. Esto es lo que uso:
from __future__ import unicode_literals, print_function
import sys
def force_encoded_string_output(func):
if sys.version_info.major < 3:
def _func(*args, **kwargs):
return func(*args, **kwargs).encode(sys.stdout.encoding or ''utf-8'')
return _func
else:
return func
class MyDummyClass(object):
@force_encoded_string_output
def __repr__(self):
return ''My Dummy Class! /N{WHITE SMILING FACE}''
En Python2, __repr__
(y __str__
) debe devolver un objeto de cadena, no un objeto Unicode. En Python3, la situación se invierte, __repr__
y __str__
deben devolver objetos unicode, no objetos de byte (cadena née):
class Foo(object):
def __repr__(self):
return u''/N{WHITE SMILING FACE}''
class Bar(object):
def __repr__(self):
return u''/N{WHITE SMILING FACE}''.encode(''utf8'')
repr(Bar())
# ☺
repr(Foo())
# UnicodeEncodeError: ''ascii'' codec can''t encode character u''/u263a'' in position 0: ordinal not in range(128)
En Python2, realmente no tienes otra opción. Debes elegir una codificación para el valor de retorno de __repr__
.
Por cierto, ¿has leído el wiki PrintFails ? Es posible que no responda directamente sus otras preguntas, pero lo encontré útil para esclarecer por qué ocurren ciertos errores.
Al usar from __future__ import unicode_literals
,
''<{}>''.format(repr(x).decode(''utf-8''))).encode(''utf-8'')
puede ser escrito más simplemente como
str(''<{}>'').format(repr(x))
asumiendo que str
codifica a utf-8
en su sistema.
Sin from __future__ import unicode_literals
, la expresión se puede escribir como:
''<{}>''.format(repr(x))
Yo uso una función como la siguiente:
def stdout_encode(u, default=''UTF8''):
if sys.stdout.encoding:
return u.encode(sys.stdout.encoding)
return u.encode(default)
Entonces mis funciones __repr__
ven así:
def __repr__(self):
return stdout_encode(u''<MyClass {0} {1}>''.format(self.abcd, self.efgh))