2

我在使用imapclient -library 进行异常处理时遇到问题。

我试图像这样处理 LoginError :

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

如果出现异常,我有这个:

Login source...ERROR: b'Invalid login'

我认为问题是,即format调用__str__()Exception-object 的 -method 并且不要尝试解码。

所以主要问题是我可以转换这个字符串

"b'Invalid login'"

像这样的普通字节对象?

b'Invalid login'

编辑 1

@lenik如果我e.message.decode()这样使用:

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

我有一个 AttributeError:

AttributeError: 'LoginError' object has no attribute 'message'

编辑 2

@snakecharmerb

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()
AttributeError: 'str' object has no attribute 'decode'
4

3 回答 3

2

imapclient的登录方法如下所示

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

我们可以看到它调用stron IMAPClientError,因此如果IMAPClientError使用bytes实例作为参数创建,那么我们最终会在LoginError*中得到字符串化字节。

有两种方法可以解决这个问题:

  1. 通过异常的元组访问原始字节args

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

  1. 使用ast.literal_eval转换字符串化异常:

msg = ast.literal_eval(str(e)).decode()

在这两种方法中,我认为 (1) 在这种特定情况下更好,但 (2) 在您有字符串化字节时更普遍适用。


*查看 github 上imaplib模块的历史,它看起来好像更改为在 Python 3.5 中的 authenticate 命令引发错误之前显式解码错误消息。所以另一个解决方案可能是升级到 Python 3.5+。

于 2019-08-19T06:53:27.573 回答
1
  1. 对于“b'xx'”-> b'xx'
>>> s = "b'a'"
>>> eval(s)
b'a'
  1. 您可以使用print('dir(e): {}'.format(dir(e)))查看属性,或将其腌制到文件中并将其加载到 ipython 进行解析。
于 2019-08-19T07:31:54.007 回答
0

您是否尝试过这样做:

>>> a = b'invalid'
>>> a
b'invalid'
>>> a.decode()
'invalid'

?


好的,第二个:

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

似乎应该在message那里,因为根据来源LoginError似乎是后代: https ://imapclient.readthedocs.io/en/2.1.0/_modules/imapclient/exceptions.html#LoginErrorimaplib.IMAP4.error

您可能希望打印dir(e)捕获异常的位置以查看它有什么——应该有一些东西被转换__str__()成字节字符串。


再一次,有一个关于 IMAP4 和 IMAPClient 库的对话,并在这里捕获异常:Catching imaplib exception (using IMAPClient package) in Python

于 2019-08-18T10:13:08.120 回答