PyQt和UTF-16代理

时间:2013-09-19 12:43:43

标签: python unicode pyqt4 utf-16

考虑以下Python代码:

In [1]: from PyQt4.QtCore import QTextCodec

In [2]: import codecs

In [3]: surrogate_raw = b'\x34\xd8\x1e\xdd'  # this is UTF-16 encoded character (surrogate pair)

In [4]: QTextCodec.codecForName('utf-16le').toUnicode(surrogate_raw)
Out[4]: '\ud834\udd1e'

In [5]: codecs.getdecoder('utf-16le')(surrogate_raw)
Out[5]: ('', 4)

如您所见,从QTextCodec :: toUnicode返回的字符串不正确。有两个字符的代码点等于代理值而不是单个字符。它不是正确的unicode(由于保留的代码点),并且此字符串无法转换为其他编码。例如,在使用utf-8的linux控制台中打印字符串是不可能的:

In [6]: incorr = QTextCodec.codecForName('utf-16le').toUnicode(surrogate_raw)

In [7]: print(incorr)
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
<ipython-input-7-556b71617dae> in <module>()
----> 1 print(incorr)

UnicodeEncodeError: 'utf-8' codec can't encode character '\ud834' in position 0: surrogates not allowed

所有QStrings都存在相同的行为,即使是由SIP包装的自定义代码返回的行为也是如此。我在64位的Ubuntu 13.04上使用Python 3.3.1和使用Python 3.3.0的Windows XP 32位测试了这段代码。

我可以猜出这个错误来自哪里 - 在Qt字符串中总是用UTF-16表示,你应该手动测试QChar是否是引导或跟踪代理。但是Python字符串是不同的,包装器会做错误的转换。

另一方面,PyQt在世界范围内被广泛使用很长时间,并且可以找到并修复像这样的基本类中的任何错误。所以我认为错误的原因是我做错了什么。我的错误在哪里?

0 个答案:

没有答案