J'ai un problème lors de la gestion des exceptions avec la imapclient -library.
I a essayé de gérer l'erreur LoginError comme ceci:
AttributeError: 'str' object has no attribute 'decode'
En cas d'exception, j'ai ceci:
try: print('Login source...'.format(args.source_user), end='', flush=False) source.login(args.source_user, args.source_pass) print('OK') except exceptions.LoginError as e: print('ERROR: {}'.format(e.args[0].decode())) exit()
Je pense Le problème est que le format
appelle la méthode __str __ ()
de l'objet Exception et n'essaye pas de décoder.
Donc, le principal la question est de savoir qui puis-je convertir cette chaîne
AttributeError: 'LoginError' object has no attribute 'message'
en un objet octets normal comme celui-ci?
try: print('Login source...'.format(args.source_user), end='', flush=False) source.login(args.source_user, args.source_pass) print('OK') except exceptions.LoginError as e: print('ERROR: {}'.format(e.message.decode())) exit()
@lenik
Si j'utilise e.message.decode ()
comme ceci:
b'Invalid login'
J'ai un AttributeError:
"b'Invalid login'"
@snakecharmerb
Login source...ERROR: b'Invalid login'
source = IMAPClient(host=args.source_server, port=args.source_port, ssl=not args.source_no_ssl) try: print('Login source...'.format(args.source_user), end='', flush=False) source.login(args.source_user, args.source_pass) print('OK') except exceptions.LoginError as e: print('ERROR: {}'.format(e)) exit()
3 Réponses :
Avez-vous essayé de faire ceci:
>>> import imaplib >>> dir(imaplib.IMAP4.error) ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', '__weakref__', 'args', 'message'] >>> imaplib.IMAP4.error.message <attribute 'message' of 'exceptions.BaseException' objects>
?
ok, deuxième prise:
>>> a = b'invalid' >>> a b'invalid' >>> a.decode() 'invalid'
semble qu'il devrait y avoir un message
là-bas, car LoginError
semble être un descendant de imaplib.IMAP4.error
selon la source: https://imapclient.readthedocs.io/en/ 2.1.0 / _modules / imapclient / exceptions.html # LoginError
Vous voudrez peut-être afficher dir (e)
où vous attrapez l'exception pour voir ce qu'elle a - il devrait y avoir quelque chose qui sera converti par __str __ ()
en une chaîne d'octets.
Là encore, il y a une conversation sur IMAP4 et la bibliothèque IMAPClient et attraper les exceptions ici: Attraper l'exception imaplib (à l'aide du package IMAPClient) en Python
Dans mon cas, "b'Invalid login '"
n'est pas un octet, c'est une chaîne. Donc, il n'a pas de decode ()
seulement encode ()
. Vous pouvez le reproduire avec str (b'some bytes ')
. Vous obtiendrez "b'some bytes '"
ce qui est en fait une chaîne.
Cher @Lukas - Je comprends parfaitement votre problème. N'utilisez simplement pas la fonction .format ()
avant e.message.decode ()
et vous serez en or =)
Hey lenik, j'ai modifié la question. e.message.decode ()
n'est malheureusement pas la solution :(
@Lukas Désolé pour la réponse erronée, s'il vous plaît, vérifiez la "deuxième prise"
__cause__
est vide / Aucun
. Même si je fais sauf IMAPClient.Error as e
qui est scripté dans la conversation. Sortie de dir (e)
: ['__cause__', '__class__', '__context__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__ ',' __reduce_ex__ ',' __repr__ ',' __setattr__ ',' __setstate__ ',' __sizeof__ ',' __str__ ',' __subclasshook__ ',' __suppress_context__ ',' __traceback__ ',' __weakref__ ',' args ',' with_traceback
.
Désolé, @Lukas - le message devrait être quelque part là-bas, mais je ne pouvais pas savoir où exactement.
La méthode de connexion de
imapclient
ressemble à this :
def login(self, username, password): """Login using *username* and *password*, returning the server response. """ try: rv = self._command_and_check( 'login', to_unicode(username), to_unicode(password), unpack=True, ) except exceptions.IMAPClientError as e: raise exceptions.LoginError(str(e)) logger.info('Logged in as %s', username) return rv
Nous pouvons voir qu'il appelle str
sur IMAPClientError
, donc si IMAPClientError
a été créé avec une instance bytes
comme argument puis nous nous retrouvons avec des octets stringifiés dans LoginError
* .
Il y a deux façons de gérer cela:
args
de l'exception: msg = e.args [0] .decode ()
msg = ast.literal_eval (str (e)). decode ()
Des deux approches, je pense que (1) est meilleur dans ce domaine cas spécifique, mais (2) est plus généralement applicable lorsque vous avez des octets stringifiés.
* En regardant l'historique du module imaplib sur github, il semble qu'il a changé pour décoder explicitement les messages d'erreur avant de déclencher les erreurs de la commande authenticate en Python 3.5. Une autre solution pourrait donc être de passer à Python 3.5+.
Merci! Votre premier moyen ne fonctionne pas. e.args [0]
est déjà la mauvaise chaîne (voir edit2).
>>> s = "b'a'" >>> eval(s) b'a'
print ('dir (e): {}'. format (dir (e)))
pour voir les attributs, ou le pickle dans un fichier et le charger dans ipython pour analyser.
Merci. Votre réponse fonctionnera, mais dans ce cas (et dans la plupart des autres cas) ast.literal_eval ()
est plus sûr à utiliser. Voir Utiliser eval () de python contre ast.literal_eval ()? .