web-dev-qa-db-fra.com

Conversion d'Exception en chaîne dans Python 3

quelqu'un at-il une idée, pourquoi ce code Python 3.2 

try:    
    raise Exception('X')
except Exception as e:
    print("Error {0}".format(str(e)))

fonctionne sans problème (à part le codage Unicode dans Windows Shell: /), mais ce 

try:    
    raise Exception('X')
except Exception as e:
    print("Error {0}".format(str(e, encoding = 'utf-8')))

lève TypeError: contraindre str: besoin d'octets, bytearray ou objet semblable à un tampon, exception trouvée?

Comment convertir une erreur en chaîne avec un encodage personnalisé?

Modifier

Cela ne fonctionne pas non plus, s'il y a\u2019 dans le message:

try:    
    raise Exception(msg)
except Exception as e:
    b = bytes(str(e), encoding = 'utf-8')
    print("Error {0}".format(str(b, encoding = 'utf-8')))

Mais pourquoi str () ne peut-il pas convertir une exception en octets en interne?

42
ts.

Dans Python 3.x, str(e) devrait pouvoir convertir n'importe quelle Exception en chaîne, même si elle contient des caractères Unicode.

Donc, à moins que votre exception retourne réellement un tableau d'octets codés UTF-8 dans sa méthode __str__() personnalisée, str(e, 'utf-8') ne fonctionnera pas comme prévu (il essaierait d'interpréter une chaîne de caractères Unicode 16 bits dans RAM en tant que tableau d'octets codés UTF-8 ...)

Mon hypothèse est que votre problème n'est pas str() mais print() (c'est-à-dire l'étape qui convertit la chaîne Python Unicode en quelque chose qui est vidé sur votre console). Voir cette réponse pour trouver des solutions: Python, Unicode et la console Windows

40
Aaron Digulla

Essayez ceci, ça devrait marcher.

try:    
    raise Exception('X')
except Exception as e:
    print("Error {0}".format(str(e.args[0])).encode("utf-8"))

Considérant que vous avez seulement un message dans votre tuple interne.

10
Sebastiano Merlino

En Python3, string n'a pas d'attribut tel que codage. C'est toujours unicode en interne. Pour les chaînes encodées, il y a des tableaux d'octets:

s = "Error {0}".format(str(e)) # string
utf8str = s.encode("utf-8") # byte array, representing utf8-encoded text
4
hamstergene

En Python 3, vous êtes déjà dans "unicode space" et n'avez pas besoin d'encodage. Selon ce que vous souhaitez réaliser, vous devez effectuer la conversion immédiatement avant de procéder.

Par exemple. vous pouvez convertir tout cela en bytes(), mais plutôt dans le sens

bytes("Error {0}".format(str(e)), encoding='utf-8')

.

3
glglgl

Il existe une conversion indépendante de la version ici:

# from the `six` library
import sys
PY2 = sys.version_info[0] == 2
if PY2:
    text_type = unicode
    binary_type = str
else:
    text_type = str
    binary_type = bytes

def exc2str(e):
    if e.args and isinstance(e.args[0], binary_type):
        return e.args[0].decode('utf-8')
    return text_type(e)

et teste pour cela:

def test_exc2str():
    a = u"\u0856"
    try:
        raise ValueError(a)
    except ValueError as e:
        assert exc2str(e) == a
        assert isinstance(exc2str(e), text_type)
    try:
        raise ValueError(a.encode('utf-8'))
    except ValueError as e:
        assert exc2str(e) == a
        assert isinstance(exc2str(e), text_type)
    try:
        raise ValueError()
    except ValueError as e:
        assert exc2str(e) == ''
        assert isinstance(exc2str(e), text_type)
0
tsionyx