在Python 2 + GTK中检测/删除不成对的代理字符

时间:2013-09-07 12:18:12

标签: python unicode utf-8 gtk glib

在Python 2.7中,我可以成功将Unicode字符串"abc\udc34xyz"转换为UTF-8(结果为"abc\xed\xb0\xb4xyz")。但是当我将UTF-8字符串传递给例如。 pango_parse_markup()g_convert_with_fallback(),我收到“转换输入中的字节序列无效”等错误。显然GTK / Pango函数检测到字符串中的“不成对的代理”并且(正确地)拒绝它。

Python 3甚至不允许将Unicode字符串转换为UTF-8(错误:“'utf-8'编解码器无法编码位置3中的字符'\ udc34':代理不允许”),但我可以运行"abc\udc34xyz".encode("utf8", "replace")来获取有效的UTF8字符串,其中单独的代理替换为其他字符。这对我来说很好,但我需要一个Python 2的解决方案。

所以问题是:在Python 2.7中,如何将这个Unicode字符串转换为UTF-8,同时用U + FFFD等替换字符替换单独的代理?最好只使用标准的Python函数和GTK / GLib / G ...函数。

顺便说一下。 Iconv可以将字符串转换为UTF8,但只是删除坏字符而不是用U + FFFD替换它。

2 个答案:

答案 0 :(得分:9)

您可以在编码前自行进行替换:

import re

lone = re.compile(
    ur'''(?x)            # verbose expression (allows comments)
    (                    # begin group
    [\ud800-\udbff]      #   match leading surrogate
    (?![\udc00-\udfff])  #   but only if not followed by trailing surrogate
    )                    # end group
    |                    #  OR
    (                    # begin group
    (?<![\ud800-\udbff]) #   if not preceded by leading surrogate
    [\udc00-\udfff]      #   match trailing surrogate
    )                    # end group
    ''')

u = u'abc\ud834\ud82a\udfcdxyz'
print repr(u)
b = lone.sub(ur'\ufffd',u).encode('utf8')
print repr(b)
print repr(b.decode('utf8'))

输出:

u'abc\ud834\U0001abcdxyz'
'abc\xef\xbf\xbd\xf0\x9a\xaf\x8dxyz'
u'abc\ufffd\U0001abcdxyz'

答案 1 :(得分:-1)

以下是解决这个问题的原因:

invalid_string.encode('utf16').decode('utf16', 'replace')

我的理解是代理对是UTF-16的一部分,这就是为什么使用UTF-8进行编码/解码并没有做任何事情。