如何将像字符串这样的字节转换为普通字节?

How to convert a byte like string to normal bytes?

我在使用 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__() 方法,不要尝试解码。

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

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

你试过这样做吗:

>>> 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 似乎是 imaplib.IMAP4.error 的后代:https://imapclient.readthedocs.io/en/2.1.0/_modules/imapclient/exceptions.html#LoginError

您可能想要打印 dir(e) 捕获异常的地方以查看它有什么 -- 应该有一些东西被 __str__() 转换为字节字符串。


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

imapclient 的登录方法类似于 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

我们可以看到它在 IMAPClientError 上调用了 str,所以如果 IMAPClientError 是用 bytes 实例作为参数创建的,那么我们最终会得到字符串化的字节在 LoginError*.

有两种处理方法:

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

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

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

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

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


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

  1. for "b'xx'" --> b'xx'
>>> s = "b'a'"
>>> eval(s)
b'a'
  1. 您可以使用 print('dir(e): {}'.format(dir(e))) 查看属性,或者将其 pickle 到文件并加载到 ipython 进行解析。