Python unicode字符串被psycopg拒绝

2024-04-20 15:04:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我收到了一个来自wild的unicode字符串,它导致一些psycopg2语句失败。在

我已将问题归结为SSCE:

import psycopg2
conn = psycopg2.connect(...)
cur = conn.cursor()
x = u'\ud837'
cur.execute("SELECT %s", (x,))
print cur.fetchone()

运行此操作会出现以下异常:

^{pr2}$

根据一些评论,很明显,这个特殊的角色是代理对的一半,因此不能独自生活。在

具体来说,我正在寻找一种机制来检测python2中字符串何时包含不完整的代理项对。在

我发现的导致异常的一种方法是尝试x.encode('utf16').decode('utf16'),但是,由于我不完全了解相关的风险,我在这里会有点担心。在

编辑:将导致问题的SSCE字符串缩减为单个字符,根据注释添加信息。在


Tags: 字符串import代理executeconnectunicode语句conn
2条回答

要检测该字符串是无效的utf-8,只需在psycopg2中执行它之前,在try/except中对其进行编码。在

至于是什么导致了这个问题,在字符串的中间有一个特定的字符,utf-16编码:\U000d8a85。所以不是说Postgres不考虑它utf-8,它真的不是

字符串u'\ud837'surrogate pair中的一个单独成员组成,两个物理字符按顺序出现以形成一个逻辑字符。因此,它没有定义Unicode码位,而是UTF-16编码的实现细节,它使用它将整个码位范围打包成16位代码单元。Python3正确地拒绝了以任何字节编码(包括UTF-*变体)对单独代理项进行编码的尝试。在

字符串可能源于一个内部使用UTF-16的系统(例如Java、C#、Windows或用16位Py_UNICODE构建的python2)天真地缩短了字符串而不考虑代理项。在

this answer获取regex,应该可以使用以下代码高效地检测此类字符串:

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
    ''')

def invalid_unicode(s):
    assert isinstance(s, unicode)
    return lone.search(s) is not None

相关问题 更多 >