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?
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
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.
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
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')
.
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)