首页 文章

“surrogateescape”无法逃避某些角色

提问于
浏览
5

关于在Python中读取和写入文本文件,one of the main Python contributors mentions这与 surrogateescape Unicode错误处理程序有关:

[surrogateescape]通过在Unicode代码点空间的一小部分使用中将数据拖出来处理解码错误 . 编码时,它会将那些隐藏的值转换回无法正确解码的确切原始字节序列 .

但是,在打开文件然后尝试将输出写入另一个文件时:

input_file = open('someFile.txt', 'r', encoding="ascii", errors="surrogateescape")
output_file = open('anotherFile.txt', 'w')

for line in input_file:
    output_file.write(line)

结果是:

File "./break-50000.py", line 37, in main
    output_file.write(line)
UnicodeEncodeError: 'utf-8' codec can't encode character '\udcc3' in position 3: surrogates not allowed

请注意,输入文件不是ASCII . 但是,它会在包含非ASCII字符的数百行之前横切它,然后才会在一个特定行上抛出异常 . 输出文件必须是ASCII并且丢失一些字符就好了 .

这是在解码为UTF-8时抛出错误的行:

'Zoë's Coffee House'

这是十六进制编码:

$ cat z.txt | hd
00000000  27 5a 6f c3 ab 5c 27 73  20 43 6f 66 66 65 65 20  |'Zo..\'s Coffee |
00000010  48 6f 75 73 65 27 0a                              |House'.|
00000017

Why might the surrogateescape Unicode Error Handler be returning a character that is not ASCII? 这是在Kubuntu Linux 12.10上的Python 3.2.3 .

3 回答

  • 0

    为什么surrogateescape Unicode Error Handler会返回一个不是ASCII的字符?

    因为这就是明确的做法 . 这样你可以用另一种方式使用相同的错误处理程序,它将知道该怎么做 .

    3>> b"'Zo\xc3\xab\\'s'".decode('ascii', errors='surrogateescape')
    "'Zo\udcc3\udcab\\'s'"
    3>> "'Zo\udcc3\udcab\\'s'".encode('ascii', errors='surrogateescape')
    b"'Zo\xc3\xab\\'s'"
    
  • 7

    单独的代理不应该用UTF-8编码 - 这正是它用于无效输入的内部表示的原因 .

    在现实生活中,获取对于“假定”所在的编码无效的数据是很常见的 . 例如,这个问题的灵感来自于在ASCII或UTF-8时出现在Latin-1中的文本 . 预计 . 我把“假设”放在引号中,因为“编码信息”很常见,只是猜测,可能与实际文件无关 .

    默认情况下,xml处理(以及大多数unicode处理)是严格的 - 即使它可以正常处理数百个其他行,整个过程也会放弃 .

    解码错误=替换会把那条线变成“Zo?的咖啡馆”,这是一个改进 . (好吧,除非你试图用无效的其他东西替换无效字符 - 并且官方unicode替换字符在ASCII中无效,这就是'?'通常用于编码的原因 . )

    当程序员决定“你知道什么?我不在乎数据是否是垃圾 . 也许我有错误的编解码器......所以我只是按原样传递未知字节 . ”使用了surrogateescape . Python必须在内部存储(但避免解释)这些字节,直到它们被传递 .

    使用不成对的代理允许Python存储无效字节而无需额外转义 . 正因为未配对的代理人无效,他们永远不会出现在有效的输入中 . (如果它们无论如何都会出现,它们将被解释为一对无法识别的字节,这两个字节都会被保留用于输出 . )

    原始海报的问题在于他试图直接打印出内部表示,而不是首先反转映射,而内部表示具有(故意)无效的字节...因此默认(严格)错误处理程序被拒绝 .

  • 3

    为什么应该在utf-8中编码低代理DCC3?这是不允许和无用的,因为代理不是一个角色 . 找到属于低代理的高代理,解码其代码点,然后为代码点创建正确的utf-8序列 .

相关问题