python raw_input带有包含字符串的重音的奇怪行为

时间:2012-06-17 02:51:13

标签: python unicode diacritics raw-input

我正在编写一个程序,要求用户输入包含重音的输入。测试用户输入字符串以查看它是否与程序中声明的字符串匹配。如下所示,我的代码无效:


# -*- coding: utf-8 -*-

testList = ['má']
myInput = raw_input('enter something here: ')

print myInput, repr(myInput)
print testList[0], repr(testList[0])
print myInput in testList

使用pydev 在eclipse中输出

enter something here: má
m√° 'm\xe2\x88\x9a\xc2\xb0'
má 'm\xc3\xa1'
False

IDLE

中输出

enter something here: má
má u'm\xe1'
má 'm\xc3\xa1'

Warning (from warnings module):
  File "/Users/ryanculkin/Desktop/delete.py", line 8
    print myInput in testList
UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
False

在比较两个字符串时,如何让我的代码打印出来?

另外,我注意到在同一输入上运行此代码的结果是不同的,这取决于我是使用eclipse还是IDLE。为什么是这样?我的最终目标是将我的程序放在网上;有什么我需要注意的,因为结果似乎很不稳定吗?

3 个答案:

答案 0 :(得分:9)

您遇到的是raw_input为您提供了一个字节字符串,但您要比较的字符串是一个Unicode字符串。 Python 2尝试将它们转换为要比较的公共类型,但这会失败,因为它无法猜测字节字符串的编码 - 因此,您的解决方案是明确地进行转换。

作为一项规则,您应该将程序中的所有字符串作为unicode字符串浮动 - 您以字节形式读取的任何内容都会立即转换为unicode;你在程序中作为文字的任何东西,使它成为unicode文字,除非由于某种原因显然需要是一个字节串。这导致unicode sandwich,这通常会让您的生活更轻松。

对于文字,您要么将字符串声明为u'má',要么:

from __future__ import unicode_literals

靠近脚本顶部以使'un-prefixed strings' unicode。你得到的错误暗示你已经完成了这一点。

要读取unicode字符串,您需要意识到raw_input为您提供了字节字符串 - 因此,您需要使用其.decode方法进行转换。您需要传递.decode STDIN的编码 - 可用sys.stdin.encoding(不要只假设这是UTF8 - 它通常是,但并非总是如此) - 所以,整行将是:

string = raw_input(...).decode(sys.stdin.encoding) 

但到目前为止最简单的方法是升级到Python 3,如果可以的话 - input()(其行为类似于Py2 raw_input)会给你一个unicode字符串(它调用{ {1}}对于你,所以你不必记住它),默认情况下,无前缀的字符串是unicode字符串。这使得使用重音字符更加容易 - 这实际上意味着你正在尝试的逻辑只能在Py3中工作,因为它做了正确的事情。

但请注意,您看到的错误仍会在Py3中显示 - 但由于它默认情况下做的正确,所以您必须努力工作才能遇到它。但是,如果你这样做,比较只会是False,没有任何警告 - Py3不会试图在字节和unicode字符串之间进行隐含转换,因此任何字节字符串将始终与任何unicode字符串进行比较,并且尝试对它们进行排序将抛出异常。

答案 1 :(得分:0)

一种选择是删除字符重音符号,如:: What is the best way to remove accents in a python unicode string? >在 other locations 中阅读后,我发现你可以在# -*- coding: utf-8 -*-之后设置#!/usr/bin/python选项,以便将所有字符串保留在unicode中,这可能有所帮助。在这种情况下,您可能需要运行s = raw_input().decode('utf8')才能获得正确的unicode。

答案 2 :(得分:0)

请注意,您与IDLE与PyDev有所不同,因为PyDev会将PYTHONIOENCODING设置为启动配置中的编码>常见>编码。并且还将使用该编码执行sys.setdefaultencoding(它具有自定义sitecustomize.py)。