Skip to main content
 首页 » 编程设计

python之将字节解码为 unicode 字符串

2025年05月04日24落叶

问题是如何提取字符串,在字符串中表示为字节(警告)?我的实际意思是:

>>> s1 = '\\xd0\\xb1'  #  But this is NOT bytes of s1! s1 should be 'б'! 
'\\xd0\\xb1' 
>>> s1[0] 
'\\' 
>>> len(s1)            #  The problem is here: I thought I would see (2), but: 
8 
>>> type(s1) 
<class 'str'> 
>>> type(s1[0]) 
<class 'str'> 
>>> s1[0] == '\\' 
True 

那么我如何将 s1 转换为 'б'(西里尔符号 - '\xd0\xb1' 的真实表示)。我已经在这里问了一个类似的问题,但我的错误被误解为 s1 的真实代表观点(我认为 '\' 是 '\',而不是 '\\')。

请您参考如下方法:

试试下面的代码。警告,这只是一个概念证明。当文本还包含写为非转义序列的字符时,替换必须以更复杂的方式完成(稍后我会在需要时展示)。请参阅下面的评论。

import binascii 
 
s1 = '\\xd0\\xb1' 
print('s1 =', repr(s1), '=', list(s1))            # list() to emphasize what are the characters 
 
s2 = s1.replace('\\x', '') 
print('s2 =', repr(s2)) 
 
b = binascii.unhexlify(s2) 
print('b =', repr(b), '=', list(b)) 
 
s3 = b.decode('utf8') 
print('s3 =', ascii(s3)) 
 
with open('output.txt', 'w', encoding='utf-8') as f: 
    f.write(s3) 

它在 concole 上打印:

c:\__Python\user\so20210201>py a.py 
s1 = '\\xd0\\xb1' = ['\\', 'x', 'd', '0', '\\', 'x', 'b', '1'] 
s2 = 'd0b1' 
b = b'\xd0\xb1' = [208, 177] 
s3 = '\u0431' 

并将字符写入output.txt 文件。

问题是这个问题结合了 unicode 转义和转义二进制值。换句话说,unicode 字符串可以包含一些以某种方式表示二进制值的序列;但是,您不能将该二进制值直接强制转换为 unicode 字符串,因为任何 unicode 字符实际上都是一个抽象整数,并且整数可以用多种方式表示(作为字节序列)。

如果 unicode 字符串包含转义序列,如 \\n,则可以使用 bytes.decode() 的 'unicode_escape' 处方,以不同的方式完成。但是,在这种情况下,您既需要从 ascii 转义序列解码,又需要从 utf-8 解码。

更新:这是一个将您的字符串类型转换为其他 ascii 字符(即不仅是转义序列)的函数。该函数使用有限自动机 - 起初可能看起来太复杂(实际上它只是冗长)。

def userDecode(s): 
    status = 0 
    lst = []                       # result as list of bytes as ints 
    xx = None                      # variable for one byte escape conversion 
    for c in s:                    # unicode character 
        print(status, ' c ==', c)  ## just for debugging 
        if status == 0: 
            if c == '\\': 
                status = 1         # escape sequence for a byte starts 
            else: 
                lst.append(ord(c)) # convert to integer 
 
        elif status == 1:          # x expected 
            assert(c == 'x') 
            status = 2 
 
        elif status == 2:          # first nibble expected 
            xx = c 
            status = 3 
 
        elif status == 3:          # second nibble expected 
            xx += c 
            lst.append(int(xx, 16)) # this is a hex representation of int 
            status = 0 
 
    # Construct the bytes from the ordinal values in the list, and decode 
    # it as UTF-8 string. 
    return bytes(lst).decode('utf-8') 
 
 
if __name__ == '__main__': 
 
    s = userDecode('\\xd0\\xb1whatever') 
    print(ascii(s))    # cannot be displayed on console that does not support unicode 
 
    with open('output.txt', 'w', encoding='utf-8') as f: 
        f.write(s) 

另请查看生成的文件。删除调试打印。它在控制台上显示以下内容:

c:\__Python\user\so20210201>b.py 
0  c == \ 
1  c == x 
2  c == d 
3  c == 0 
0  c == \ 
1  c == x 
2  c == b 
3  c == 1 
0  c == w 
0  c == h 
0  c == a 
0  c == t 
0  c == e 
0  c == v 
0  c == e 
0  c == r 
'\u0431whatever'