Question

Dernièrement, j'ai eu beaucoup de problèmes avec __repr__(), format(), et encodages. Devrait la sortie de __repr__() être encodé ou être une chaîne Unicode? Y a-t-il un meilleur encodage pour le résultat de __repr__() Dans Python? Ce que je veux sortir a des caractères non ASCII.

J'utilise Python 2.x et je veux écrire du code qui peut facilement être adapté à Python 3. Le programme utilise ainsi

# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function  # The 'Hello' literal represents a Unicode object

Voici quelques problèmes supplémentaires qui me dérangent, et je cherche une solution qui les résout:

  1. L'impression d'un terminal UTF-8 devrait fonctionner (j'ai sys.stdout.encoding mis à UTF-8, mais il serait préférable que d'autres cas fonctionnent aussi).
  2. La tuyauterie de la sortie dans un fichier (encodées dans UTF-8) devrait fonctionner (dans ce cas, sys.stdout.encoding est None).
  3. Mon code pour beaucoup __repr__() Les fonctions ont actuellement beaucoup return ….encode('utf-8'), et c'est lourd. Y a-t-il quelque chose de robuste et de plus léger?
  4. Dans certains cas, j'ai même des bêtes laides comme return ('<{}>'.format(repr(x).decode('utf-8'))).encode('utf-8'), c'est-à-dire, la représentation des objets est décodée, mise dans une chaîne de formatage, puis réencodée. Je voudrais éviter de telles transformations alambiquées.

Que recommanderiez-vous de faire pour écrire simple __repr__() Fonctions qui se comportent bien en ce qui concerne ces questions d'encodage?

Était-ce utile?

La solution

Dans Python2, __repr__ (et __str__) doit renvoyer un objet String, pas un objet Unicode. Dans Python3, la situation est inversée, __repr__ et __str__doit retourner les objets Unicode, pas les objets byte (née string):

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)

Dans Python2, vous n'avez pas vraiment le choix. Vous devez choisir un encodage pour la valeur de retour de __repr__.

Au fait, avez-vous lu le Wiki printfails? Il peut ne pas répondre directement à vos autres questions, mais j'ai trouvé cela utile pour éclairer les raisons pour lesquelles certaines erreurs se produisent.


Lors de l'utilisation from __future__ import unicode_literals,

'<{}>'.format(repr(x).decode('utf-8'))).encode('utf-8')

peut être plus simplement écrit comme

str('<{}>').format(repr(x))

en supposant str code pour utf-8 sur votre système.

Sans pour autant from __future__ import unicode_literals, l'expression peut être écrite comme:

'<{}>'.format(repr(x))

Autres conseils

Je pense qu'un décorateur peut gérer __repr__ incompatibilités d'une manière saine. Voici ce que j'utilise:

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}'

J'utilise une fonction comme ce qui suit:

def stdout_encode(u, default='UTF8'):
    if sys.stdout.encoding:
        return u.encode(sys.stdout.encoding)
    return u.encode(default)

Alors mon __repr__ Les fonctions ressemblent à ceci:

def __repr__(self):
    return stdout_encode(u'<MyClass {0} {1}>'.format(self.abcd, self.efgh))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top