为什么Python 2的raw_input输出Unicode字符串?

5

我在Codecademy的Python教程上尝试了以下内容

hobbies = []

# Add your code below!
for i in range(3):
    Hobby = str(raw_input("Enter a hobby:"))
    hobbies.append(Hobby)

print hobbies

使用此方法,一切都很好,但如果我尝试

Hobby = raw_input("Enter a hobby:")

我得到了 [u'Hobby1', u'Hobby2', u'Hobby3']。这里的额外的 u 是从哪里来的?

3
也许你可以在这里找到答案。问题是Python字符串以[u'String']的形式打印输出。 - KIDJourney
你正在使用哪个版本的Python?在Python 2.7中,我两者都收到相同的结果。u代表Unicode编码。 - EbraHim
2
也许这与它运行的控制台有关? - Byte Commander
我使用了CodeAcademy的Web控制台。我认为它运行的是2.7版本。 - user1936752
@KIDJourney 这不是重复的问题:“为什么raw_input()返回Unicode”(而在Python 2中应该返回字节串)与“为什么打印包含Unicode字符串的列表会产生[u'']”是两个不同的问题。 - jfs
4个回答

8
这个问题的主题可能会有点误导性:Python 2的raw_input()通常返回一个字节字符串,而不是Unicode字符串。
但是,如果它或sys.stdin已被更改或替换(由应用程序或作为Python的另一种实现的一部分),它可能返回Unicode字符串。
因此,我认为@ByteCommander的评论是正确的:
也许这与它运行的控制台有关?
Codecademy使用的Python表面上是2.7,但是(a)它是通过使用Emscripten将Python解释器编译成JavaScript实现的,(b)它在浏览器中运行;因此,在这些因素之间,Codecademy可能注入了一些字符串编码和解码,这在纯vanilla CPython中不存在。
注意:我自己没有使用过Codecademy,也没有任何内部了解。

只想说这几乎肯定就是了。我正在寻找一般性答案,而且肯定是因为我在 Codecademy Python 2.7 课程中进行了越野操作导致的。这一定是他们那边的问题。很高兴知道默认行为是合理的。 - jerclarke

4

'u' 表示它是Unicode编码。你也可以使用 raw_input().encode('utf8') 来将其转换为字符串。

编辑: 我在Python 2.7中检查后发现它返回字节字符串而不是Unicode字符串,所以问题应该出现在其他地方。

编辑: 如果sys.stdin.encoding是Unicode,则raw_input()返回Unicode。

在codeacademy Python环境中,sys.stdin.encoding和sys.stdout.decoding都没有设置, 默认的编码方式是ASCII。

只有当Python无法从环境中找到合适的编码方式时,才会使用此默认编码方式。


Python 2.X 中的 raw_input() 返回字节字符串,而不是 Unicode 字符串。还有其他问题。 - Mark Tolonen
@MarkTolonen:在Python 3中没有raw_input()函数,因此可以肯定地说raw_input()始终返回一个字节串,除非第三方模块(如win-unicode-console)覆盖了其行为。 - jfs
@MarkTolonen你说过“在Python 2.X中,raw_input()返回字节字符串”,这可能被解释为在Python 3上的行为不同。我说过“在Python 3上没有raw_input()”,以消除歧义。我同意你的观点,我的评论只是一个补充。 - jfs
1
这里的主要问题是,这个答案提供了明显错误的信息。:( 我理解即使它是错误的,因为提问者不知道更好的方法,它也可能被接受。但是它是如何获得多个赞成票的呢? - John Y
我根据@John Y的评论取消了答案的接受。 - user1936752
显示剩余2条评论

3

多余的 u 是从哪里来的?

  • raw_input() 在你的环境中返回 Unicode 字符串
  • 如果你打印一个列表(转换成字符串),则会为每个项目调用 repr()
  • Unicode 字符串的文本表示形式 (repr()) 与 Python 中的 Unicode 文字相同:u'abc'

这就是为什么 print [raw_input()] 可能会产生:[u'abc']

在第一个代码示例中看不到 u'',因为 str(unicode_string) 调用了等效于 unicode_string.encode(sys.getdefaultencoding()) 即将 Unicode 字符串转换为字节字符串——除非你有意这样做,否则不要这样做。

raw_input() 能返回 unicode 吗?

可以

#!/usr/bin/env python2
"""Demonstrate that raw_input() can return Unicode."""
import sys

class UnicodeFile:
    def readline(self, n=-1):
        return u'\N{SNOWMAN}'

sys.stdin = UnicodeFile()
s = raw_input()
print type(s)
print s

输出:

<type 'unicode'>

一个实际的例子是win-unicode-console包,它可以替换raw_input()来支持在Windows上输入超出控制台代码页范围的Unicode字符。相关:这里是为什么应该替换sys.stdout

raw_input()可以返回unicode吗?

可以。

raw_input()记录返回一个字符串

该函数从输入中读取一行,将其转换为字符串(去除尾随换行符),并返回该字符串。

Python 2中的字符串可以是字节串或Unicode字符串:isinstance(s, basestring)

CPython实现的raw_input()支持Unicode字符串,builtin_raw_input()可以调用PyFile_GetLine(),而PyFile_GetLine()认为bytestrings和Unicode字符串都是字符串——否则会引发TypeError("object.readline() returned non-string")异常。请注意保留HTML标记。

1
您可以在将字符串添加到列表之前对其进行编码:
hobbies = []

# Add your code below!
for i in range(3):
    Hobby = raw_input("Enter a hobby:")
    hobbies.append(Hobby.encode('utf-8')

print hobbies

在这种情况下,编码是不必要的。只有当第一行没有以str()开头时才需要它。 - user1936752

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接