Unicode(西里尔文)字符索引,用python重新编写

Unicode(西里尔文)字符索引,用python重新编写,python,python-2.7,unicode,Python,Python 2.7,Unicode,我正在使用西里尔拼字法书写俄语单词。除了在str中有多少(但不是全部)西里尔字母被编码为两个字符外,其他一切都正常工作。例如: >>>print ["ё"] ['\xd1\x91'] 如果我不想索引字符串位置或识别字符的位置并用另一个字符替换它(比如说“e”,而不使用diaeresis),那么这不会是一个问题。显然,当前缀为u时,这两个“字符”被视为一个,如u“ё”: 但是strs是作为变量传递的,因此不能以u作为前缀,unicode()给出了一个UnicodeDecodeE

我正在使用西里尔拼字法书写俄语单词。除了在
str
中有多少(但不是全部)西里尔字母被编码为两个字符外,其他一切都正常工作。例如:

>>>print ["ё"]
['\xd1\x91']
如果我不想索引字符串位置或识别字符的位置并用另一个字符替换它(比如说
“e”
,而不使用diaeresis),那么这不会是一个问题。显然,当前缀为u时,这两个“字符”被视为一个,如
u“ё”

但是
str
s是作为变量传递的,因此不能以u作为前缀,
unicode()
给出了一个
UnicodeDecodeError
(ascii编解码器无法解码…)


所以。。。我该怎么做?如果有帮助的话,我正在使用python 2.7,这里有两种可能的情况

您的
str
表示有效的UTF-8编码数据,或者不表示

如果它表示有效的UTF-8数据,则可以使用
mystring.decode('UTF-8')
将其转换为Unicode对象。在它成为一个
unicode
实例之后,它将按字符而不是按字节进行索引,正如您已经注意到的那样

如果其中包含无效的字节序列。。。你有麻烦了。这是因为“这个字节代表哪个字符?”的问题不再有明确的答案。当你说“第三个字符”时,你必须准确地确定你的意思,因为字节序列根本不代表UTF-8中的特定Unicode字符


解决此问题的最简单方法可能是使用
ignore\u errors
标志来
decode()
。这将完全丢弃无效的字节序列,只提供字符串的“正确”部分。

这些实际上是不同的编码:

>>>print ["ё"]
['\xd1\x91']
>>>print [u"ё"]
[u'\u0451']
您看到的是列表中元素的
\uuu repr\uu
。而不是unicode对象的
\uuu str\uu
版本

但是str是作为变量传递的,因此不能被忽略 前缀为u

您的意思是数据是字符串,需要转换为unicode类型:

>>> for c in ["ё"]: print repr(c)
...
'\xd1\x91'
您需要将双字节字符串强制转换为双字节宽度的unicode:

>>> for c in ["ё"]: print repr(unicode(c, 'utf-8'))
...
u'\u0451'

您将看到,通过这种转换,它们非常好。

要将字节转换为Unicode,您需要知道相应的字符编码并调用:

编码取决于数据源。它可以是任何东西,例如,如果数据来自网页;看

不要在字节文本中使用非ascii字符(在Python 3中明确禁止)。添加来自未来导入unicode文本的
,将所有
“abc”
文本视为unicode文本

注意:单个用户感知的字符可能跨越多个Unicode代码点,例如:

>>> print(u'\u0435\u0308')
ё

然后可以使用str.format作为前缀,或者使用unicodeI的正确编码。在上一个示例中,假设您提供了带有组合变音符号的“e”?是的,它是组合变音符号
unicodedata.normalize('NFC',u'\u0435\u0308')==u'\u0451'==u'ё'
,如果我想把它移回原来的双字节格式,我就使用
mystring.encode('ascii')
?@sautedman它不是双字节格式-UTF-8是可变长度编码。但是是的,如果你想的话,你可以叫“encode”。
>>> b'\xd1\x91'.decode('utf-8')
u'\u0451'
>>> print(u'\u0435\u0308')
ё