如何在Python中将拉丁字符转换为quoted-printable编码?
Python quopri模块为何不编码拉丁字符?如何强制编码所有字符?
我使用Python标准库的quopri模块时发现,编码包含西里尔文和拉丁文的混合字符串时,只有西里尔字符被转换为Quoted-Printable格式,而拉丁字符(如Fly)和空格、括号等ASCII可打印字符直接保留,没有被编码,不符合预期。
测试代码
import quopri fly_as_quoted_printable = b'=28=46=6C=79=29' fly_as_bytes = quopri.decodestring(fly_as_quoted_printable) fly_as_utf8 = fly_as_bytes.decode('utf-8') print('\nСonverting `quoted_printable` to bytes and string is ok:') print(f'fly_as_quoted_printable= {fly_as_quoted_printable}') print(f'fly_as_bytes= {fly_as_bytes}') print(f'fly_as_utf8= {fly_as_utf8}') cyrillic_and_latin_mixed_as_bytes = bytes('Полёт (Fly)', 'utf-8') quoted_printable = quopri.encodestring(cyrillic_and_latin_mixed_as_bytes) print('\nBut converting latin characters as bytes to `quoted_printable` does not work:') print(f'cyrillic_and_latin_mixed_as_bytes= {cyrillic_and_latin_mixed_as_bytes}') print(f'quotep_printable= {quoted_printable}')
运行输出
Сonverting `quoted_printable` to bytes and string is ok: fly_as_quoted_printable= b'=28=46=6C=79=29' fly_as_bytes= b'(Fly)' fly_as_utf8= (Fly) But converting latin characters as bytes to `quoted_printable` does not work: cyrillic_and_latin_mixed_as_bytes= b'\xd0\x9f\xd0\xbe\xd0\xbb\xd1\x91\xd1\x82 (Fly)' quotep_printable= b'=D0=9F=D0=BE=D0=BB=D1=91=D1=82 (Fly)'
原因分析
这是quopri模块的默认行为,完全符合Quoted-Printable编码的规范(RFC 2045):规范规定ASCII可打印字符(ASCII码33-126,包括拉丁字母、数字、常见符号如()、空格等)可以直接保留,不需要编码;只有非ASCII字符、控制字符、以及特殊字符=需要被编码为=XX格式(XX为字节的十六进制表示)。
解决方案:强制编码所有字符
如果需要将所有字节都转换为Quoted-Printable格式(包括ASCII可打印字符),可以自定义编码函数,遍历每个字节并手动转换:
import quopri def encode_all_bytes_to_qp(data: bytes) -> bytes: """将所有字节编码为Quoted-Printable格式""" return b''.join(b'=%02X' % byte for byte in data) # 测试 cyrillic_and_latin_mixed_as_bytes = bytes('Полёт (Fly)', 'utf-8') quoted_printable = encode_all_bytes_to_qp(cyrillic_and_latin_mixed_as_bytes) print(f'原始字节: {cyrillic_and_latin_mixed_as_bytes}') print(f'全编码QP格式: {quoted_printable}')
运行输出:
原始字节: b'\xd0\x9f\xd0\xbe\xd0\xbb\xd1\x91\xd1\x82 (Fly)' 全编码QP格式: b'=D0=9F=D0=BE=D0=BB=D1=91=D1=82=20=28=46=6C=79=29'
如果需要兼容quopri的其他特性(如换行处理),也可以基于quopri.encode函数修改编码规则,但自定义遍历的方式最直接可控。
内容的提问来源于stack exchange,提问作者Comrade Che
相关产品推荐
相关产品推荐

