考虑以下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在世界范围内被广泛使用很长时间,并且可以找到并修复像这样的基本类中的任何错误。所以我认为错误的原因是我做错了什么。我的错误在哪里?