【问题标题】:How to decode a string representation of a bytes object?如何解码字节对象的字符串表示?
【发布时间】:2019-07-20 05:11:41
【问题描述】:

我有一个字符串,其中包含编码字节:

str1 = "b'Output file \xeb\xac\xb8\xed\x95\xad\xeb\xb6\x84\xec\x84\x9d.xlsx Created'"

我想解码它,但我不能,因为它已经变成了一个字符串。因此我想问是否有任何方法可以将其转换为

str2 = b'Output file \xeb\xac\xb8\xed\x95\xad\xeb\xb6\x84\xec\x84\x9d.xlsx Created'

这里的str2 是一个bytes 对象,我可以使用它轻松解码

str2.decode('utf-8')

得到最终结果:

'Output file 문항분석.xlsx Created'

【问题讨论】:

    标签: python python-3.x decode


    【解决方案1】:

    你可以使用ast.literal_eval:

    >>> print(str1)
    b'Output file \xeb\xac\xb8\xed\x95\xad\xeb\xb6\x84\xec\x84\x9d.xlsx Created'
    >>> type(str1)
    <class 'str'>
    

    >>> from ast import literal_eval
    >>> literal_eval(str1).decode('utf-8')
    'Output file 문항분석.xlsx Created'
    

    【讨论】:

    • SyntaxError: bytes 只能包含 ASCII 文字字符。
    • 这表明您的输入实际上类似于"b'Output file 문í\x95\xadë¶\x84ì\x84\x9d.xlsx Created'",而不是我从您的问题中推断出的转义字符串。老实说,我认为是时候去解决那些给你带来如此混乱输入的东西了……
    • 请看我之前的评论——一旦事情变得如此混乱,你最好修复任何产生如此令人不快的字符串的东西。
    • 我自己已经转换成字节 msg = bytes("Output file " + output_filename + " Created", 'utf-8') print(msg) 通过popen().communicate发送msg () 函数在我收到通信后不支持原始 msg 我得到了上面的字节字符串列表
    【解决方案2】:

    根据您的 cmets 中提到的 SyntaxError,您在尝试打印时可能会遇到测试问题,因为在您的控制台中 stdout 设置为 ascii(您可能还会发现您的控制台确实不支持您可能尝试打印的某些字符)。您可以尝试以下方法将sys.stdout 设置为utf-8 并查看您的控制台将打印什么(只需使用下面的字符串切片和encode 来获取字节,而不是已经建议的ast.literal_eval 方法):

    import codecs
    import sys
    
    sys.stdout = codecs.getwriter('utf-8')(sys.stdout.buffer)
    
    s = "b'Output file \xeb\xac\xb8\xed\x95\xad\xeb\xb6\x84\xec\x84\x9d.xlsx Created'"
    b = s[2:-1].encode().decode('utf-8')
    

    【讨论】:

    • AttributeError: 'OutStream' 对象没有属性 'buffer'
    • @SujilDevkota - 不幸的是,我无法复制该错误。必须有一些其他环境因素(即问题中未包含的附加代码、我们不期望的某种操作系统/外壳组合等)。
    【解决方案3】:

    一个简单的方法是假设初始字符串的所有字符都在 [0,256) 范围内,并映射到同一个 Unicode 值,也就是说它是一个 Latin1 编码的字符串。

    然后转换是微不足道的:

    str1[2:-1].encode('Latin1').decode('utf8')
    

    【讨论】:

    • 谢谢,它很短,而且比我发现的解决方案更容易
    • 但有一件事是,当我单独运行此代码时它工作正常,但在我的主程序中,当我实现它时,Latin1 编码后的字符串将自动在任何 \ 前面添加 \ 所以有\\ 在字符串中因此对其进行解码使其仅删除单个斜杠。因此,上面的代码类似于 str1 [2:-1]。我认为为了逃避\字符python正在添加另一个\。我该如何处理它
    【解决方案4】:

    最后我找到了一个答案,我使用一个函数将字符串转换为不编码的字节。给定字符串

    str1 = "b'Output file \xeb\xac\xb8\xed\x95\xad\xeb\xb6\x84\xec\x84\x9d.xlsx Created'"

    现在我只在其中包含实际的编码文本

    str1[2:-1]

    并将其传递给将字符串转换为字节而不对其值进行编码的函数

    import struct
    def rawbytes(s):
        """Convert a string to raw bytes without encoding"""
        outlist = []
        for cp in s:
            num = ord(cp)
            if num < 255:
                outlist.append(struct.pack('B', num))
            elif num < 65535:
                outlist.append(struct.pack('>H', num))
            else:
                b = (num & 0xFF0000) >> 16
                H = num & 0xFFFF
                outlist.append(struct.pack('>bH', b, H))
        return b''.join(outlist)
    

    因此,调用该函数会将其转换为字节,然后进行解码

    rawbytes(str1[2:-1]).decode('utf-8')

    会给出正确的输出

    'Output file 문항분석.xlsx Created'

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-28
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 2021-10-09
      • 2019-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多