2
votes

Comment convertir un octet comme une chaîne en octets normaux?

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()

modifier 1

@lenik Si j'utilise e.message.decode () comme ceci:

b'Invalid login'

J'ai un AttributeError:

"b'Invalid login'"

modifier 2

@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()


0 commentaires

3 Réponses :


0
votes

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


6 commentaires

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.



2
votes

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:

  1. Accédez aux octets d'origine via le tuple args de l'exception:

msg = e.args [0] .decode ()

  1. Utilisez ast.literal_eval pour convertir l'exception en chaîne :

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+.


1 commentaires

Merci! Votre premier moyen ne fonctionne pas. e.args [0] est déjà la mauvaise chaîne (voir edit2).



1
votes
  1. pour "b'xx '" -> b'xx'
  2. >>> s = "b'a'"
    >>> eval(s)
    b'a'
    
    1. Vous pouvez utiliser print ('dir (e): {}'. format (dir (e))) pour voir les attributs, ou le pickle dans un fichier et le charger dans ipython pour analyser.

1 commentaires

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