如何在Python中使用代理对?

Mat*_*DMo 25 python unicode surrogate-pairs python-3.x

这是转换为表情符号的后续行动.在那个问题中,OP有一个json.dumps()带有表情符号代表对的表情符号的编码文件 - \ud83d\ude4f.他/她在阅读文件和正确翻译表情符号时遇到问题,正确的答案json.loads()文件中的每一行,json模块将处理从代理对转换回(我假设是UTF8编码的)表情符号.

所以这是我的情况:说我只有一个常规的Python 3 unicode字符串,其中包含一个代理项:

emoji = "This is \ud83d\ude4f, an emoji."
Run Code Online (Sandbox Code Playgroud)

如何处理此字符串以获取表情符号的表示?我希望得到这样的东西:

"This is , an emoji."
# or
"This is \U0001f64f, an emoji."
Run Code Online (Sandbox Code Playgroud)

我试过了:

print(emoji)
print(emoji.encode("utf-8")) # also tried "ascii", "utf-16", and "utf-16-le"
json.loads(emoji) # and `.encode()` with various codecs
Run Code Online (Sandbox Code Playgroud)

一般来说,我得到一个类似的错误UnicodeEncodeError: XXX codec can't encode character '\ud83d' in position 8: surrogates no allowed.

我在Linux上运行Python 3.5.1,$LANG设置为en_US.UTF-8.我在命令行的Python解释器和Sublime Text中运行的IPython中运行这些示例 - 似乎没有任何差异.

jfs*_*jfs 33

你已经混一个字符串\ud83d在磁盘上的JSON文件(六个大字:\ u d 8 3 d)和字符u'\ud83d'存储器(使用一个字符串在Python源代码的文字说明).它是Python 3 之间len(r'\ud83d') == 6和之间的区别len('\ud83d') == 1.

如果您看到'\ud83d\ude4f'Python字符串(2个字符),则上游存在错误.通常,你不应该得到这样的字符串.如果你得到一个,你就无法修复产生它的上游; 你可以使用surrogatepass错误处理程序修复它:

>>> "\ud83d\ude4f".encode('utf-16', 'surrogatepass').decode('utf-16')
''
Run Code Online (Sandbox Code Playgroud)

Python 2更宽松.

注意:即使你的json文件包含文字\ ud83d\ude4f(12个字符); 你不应该得到代理对:

>>> print(ascii(json.loads(r'"\ud83d\ude4f"')))
'\U0001f64f'
Run Code Online (Sandbox Code Playgroud)

注意:结果是1个字符('\U0001f64f'),而不是代理对('\ud83d\ude4f').


tri*_*eee 7

因为这是一个反复出现的问题,并且错误消息有些模糊,所以这里有更详细的说明。

代理是表达大于U + FFFF的Unicode代码点的一种方式。

回想一下,Unicode最初被指定为包含65,536个字符,但是很快发现这不足以容纳世界上所有的字形。

作为(否则为固定宽度)UTF-16编码的扩展机制,保留区被设置为包含一种用于在基本多语言平面之外表达代码点的机制:在此特殊区域中的任何代码点都必须遵循来自同一区域的另一个字符代码,并且它们一起将表示一个数字点,该数字大于旧限制。

(严格来说,代孕区域分为两半;成对的第一个代孕需要来自高代孕的一半,而第二代则来自低代孕。令人困惑的是,高代孕的U + D800-U + DBFF具有比低代理U + DC00-U + DFFF的代码点号低)。

这是一种遗留机制,专门用于支持UTF-16编码,不应在其他编码中使用;他们不需要它,而适用的标准明确指出这是不允许的。

换句话说,虽然 U + 12345可以用代理对U + D808 U + DF45表示,但是除非您专门使用UTF-16,否则应该直接直接表示它。

更详细地讲,这是如何在UTF-8中将其表示为单个字符:

0xF0 0x92 0x8D 0x85
Run Code Online (Sandbox Code Playgroud)

这是相应的代理序列:

0xED 0xA0 0x88
0xED 0xBD 0x85
Run Code Online (Sandbox Code Playgroud)

正如接受的答案中已经建议的那样,您可以往返

>>> "\ud808\udf45".encode('utf-16', 'surrogatepass').decode('utf-16').encode('utf-8')
b'\xf0\x92\x8d\x85'
Run Code Online (Sandbox Code Playgroud)

也许也请参见http://www.russellcottrell.com/greek/utilities/surrogatepaircalculator.htm