【问题标题】:How to convert a byte like string to normal bytes?如何将类似字符串的字节转换为普通字节?
【发布时间】:2019-12-23 21:23:17
【问题描述】:

我在使用 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 正在调用 Exception-object 的 __str__()-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'

【问题讨论】:

    标签: python python-3.x string byte imapclient


    【解决方案1】:
    1. 对于“b'xx'” --> b'xx'
    >>> s = "b'a'"
    >>> eval(s)
    b'a'
    
    1. 您可以使用print('dir(e): {}'.format(dir(e))) 来查看属性,或者将其腌制到文件中并加载到ipython 进行解析。

    【讨论】:

    【解决方案2】:

    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) 在您有字符串化字节时更普遍适用。


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

    【讨论】:

    • 谢谢!你的第一种方法行不通。 e.args[0] 已经是错误的字符串(参见edit2)。
    【解决方案3】:

    您是否尝试过这样做:

    >>> 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,因为根据来源https://imapclient.readthedocs.io/en/2.1.0/_modules/imapclient/exceptions.html#LoginErrorLoginError 似乎是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

    【讨论】:

    • 在我的情况下,"b'Invalid login'" 不是一个字节,它是一个字符串。所以它没有decode(),只有encode()。您可以使用str(b'some bytes') 复制它。你会得到"b'some bytes'" 实际上是一个字符串。
    • 亲爱的@Lukas -- 我完全理解你的问题。只是不要在你e.message.decode() 之前使用.format() 函数,你会很成功=)
    • 嘿列尼克,我已经修改了问题。 e.message.decode() 很遗憾不是解决方案:(
    • @Lukas 抱歉搞砸了答案,请检查“第二次拍摄”
    • __cause__ 为空/None。即使我在对话中编写了except IMAPClient.Error as edir(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']
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-26
    • 1970-01-01
    • 2014-12-07
    • 2021-02-23
    相关资源
    最近更新 更多