Python - 编码字符串 - 瑞典字母

3

我在使用Python2.6的raw_input命令时遇到了一些问题。由于某种原因,raw_input无法获取swedify()生成的转换后的字符串,这导致了编码错误。我很清楚这个问题,这就是我创建swedify()的原因。

这是我想要做的:

elif cmd in ('help', 'hjälp', 'info'):
    buffert += 'Just nu är programmet relativt begränsat,\nDe funktioner du har att använda är:\n'
    buffert += ' * historik :: skriver ut all din historik\n'
    buffert += ' * ändra <något> :: ändrar något i databasen, följande finns att ändra:\n'
    print swedify(buffert)

这段代码很有效,可以将瑞典字符输出到控制台。但是当我尝试在同一代码中使用相同的\x??值打印这段文字时:

core['goalDistance'] = raw_input(swedify('Hur långt i kilometer är ditt mål: '))
core['goalTime'] = raw_input(swedify('Vad är ditt mål i minuter att springa ' +  core['goalDistance'] + 'km på: '))

然后我得到了这个:

C:\Users\Anon>python löp.py
Traceback (most recent call last):
  File "l÷p.py", line 92, in <module>
    core['goalDistance'] = raw_input(swedify('Hur långt i kilometer är ditt mål: '))
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe5' in position 5: ordinal not in range(128)

我在网上搜索了一些“解决方案”,但它们都无效。有些人说我需要创建一个批处理脚本,在开头执行chcp ???,但我认为这不是一个干净的解决方案。

这里是swedify:

def swedify(inp):
    try:
        return inp.decode('utf-8')
    except:
        return '(!Dec:) ' + str(inp)

有没有解决方案可以让raw_input从swedify()读取我的返回值?我尝试了从encodings导入getencoder、getdecoder等,但都没有更好的结果。


1
当我在瑞典提示符上省略 swedify 并只调用 raw_input 时,它对我来说运行良好。 - Ray Toal
@Ray-Toal,你使用哪个版本的Python?另外,你的意思是当你像这样做时:raw_input('Hur långt i kilometer är ditt mål: ')。因为这对我也起作用,但是在控制台中我会得到错误格式的字符,具体取决于我在哪台机器上运行我的代码,我正在尝试找到一种通用的方法来将 å ä ö 输出到控制台(针对不同的操作系统、语言和本地化)。 - Torxed
我还测试了删除swedify调用的情况,对于raw_input也是有效的。需要注意的是,在我的机器上,我必须在开头添加# coding=utf-8才能使Python正确解析脚本:也许这会帮助其他人。 - Lynch
@Torxed Python 2.7.1。但是它在Mac上,我的终端设置为UTF-8,所以我没有代码页问题。请参考Lynch的评论并尝试使用coding=utf-8声明。 - Ray Toal
@Torxed 我认为没有一种_通用方法_可以使控制台正确显示,因为控制台是本地应用程序。虽然我可能错了。在Web浏览器中,使用HTML,您可以在所有浏览器上显示字符å,并且即使最终用户将其浏览器欺骗为使用与服务器发送的编码不同的编码,这也可以工作。但这类似于chcp的黑客技术,您确实要避免使用它。 - Ray Toal
6个回答

3

对我而言,以下设置可正常运作:

#-*- coding: utf-8 -*-
import sys
import codecs
koden=sys.stdin.encoding

a=raw_input( u'Frågan är öppen? '.encode(koden))
print a

Per


3

您提到收到编码错误的事实,这促使您首先编写了 swedify ,并且您已找到了围绕Windows命令chcp的解决方案。

在UTF-8终端上的*nix系统中,不需要使用swedify

>>> raw_input('Hur långt i kilometer är ditt mål: ')
Hur långt i kilometer är ditt mål: 100
'100'
>>> a = raw_input('Hur långt i kilometer är ditt mål: ')
Hur långt i kilometer är ditt mål: 200
>>> a
'200'

就我个人而言,当我使用 swedify 时,我会遇到与你一样的错误:

>>> def swedify(inp):
...     try:
...         return inp.decode('utf-8')
...     except:
...         return '(!Dec:) ' + str(inp)
... 
>>> swedify('Hur långt i kilometer är ditt mål: ') 
u'Hur l\xe5ngt i kilometer \xe4r ditt m\xe5l: '
>>> raw_input(swedify('Hur långt i kilometer är ditt mål: '))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe5' in position 5: ordinal not in range(128)

您的swedify函数返回一个Unicode对象。内置的raw_input函数不支持Unicode对象。

>>> raw_input("å")
åeee
'eee'
>>> raw_input(u"å")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe5' in position 0: ordinal not in range(128)

你可能想要尝试在Python 3中运行此代码。请参阅此Python bug
另外还有一个有趣的问题:如何在Python中读取Unicode输入并比较Unicode字符串?更新根据这篇博客文章,有一种方法可以设置系统的默认编码。这值得一试。

在*nix系统上这将是无用的,因为我的朋友们没有我们这些幸运儿那么开明,他们使用带有不同语言包和“默认语言”的Windows 7,这使得在没有100个解决方法的情况下很难获得一个好的整体解决方案。正如你所提到的,它不接受Unicode字符串,我可能应该已经想到了,我把swedify()部分移到一边并与raw_input一起打印出来,虽然不是很漂亮但它可以工作。raw_input(u'åäö>'.encode('iso-8859-15')) 工作得还不错,尽管会出现奇怪的字母。 - Torxed
你应该仍然能够让事情正常工作,因为Windows 7应该支持其控制台应用程序的UTF-8。请记住,Python的raw_input使用sys.stdin的编码,因此如果您可以强制该编码为UTF-8,并对sys.stdout执行相同操作,那么它会起作用吗?很抱歉我没有Windows 7盒子来测试这个。 - Ray Toal
那样做是可行的,我记得看过一个解决方案,他们在某种程度上使用decode(encode(u'...'))和'replace',但我找不到了,但是我知道这解决了很多问题。但强制使用stdin也可以工作,所以我将把帖子标记为解决方案,无论如何,Windows都是一个变通方法 :) 干杯,Ray! - Torxed
@RayToal,Windows控制台不支持UTF-8。有一个看起来支持UTF-8的代码页,但它已经破损到无法想象,并且会导致各种问题,特别是在读取多字节输入时。 - Alastair McCormack
好知道。但很难相信世界上最流行的操作系统之一选择拥有一个本地终端(控制台)应用程序,它不处理可以说是世界上最流行的 Unicode 编码。因此,操作系统背后的公司很高兴将“控制台支持”留给开源社区中的志愿者来建立对控制台 API 的支持吗?(如果是这样,那么对我来说,这就是真实比小说更奇怪的例子 :) ) - Ray Toal

2
在Windows上,控制台的本地Unicode支持存在问题。即使是表面上的UTF-8代码页也不是一个合适的解决方案。
要在Windows控制台中读写,您需要使用https://github.com/Drekin/win-unicode-console,它直接与底层控制台API一起工作,以便正确读取和写入多字节字符。

0

这个代码页的实用性有限。它具有有限的字符支持,并且不能修复读取多字节字符的问题。 - Alastair McCormack

-1

1
仅供记录,这并没有太大帮助。它只告诉文件内预期的编码方式,无法控制从套接字或者 raw_input 输入的实际输出或输入。 - Torxed

-1
很多问题的解决方案:


编辑:C:\Python??\Lib\Site.py 将 "del sys.setdefaultencoding" 替换为 "pass"

然后,
将此代码放在您的代码顶部:

sys.setdefaultencoding('latin-1')

解决瑞典语/非UTF8兼容字符的圣杯。


1
sys.setdefaultencoding()在Python3中被明确删除,并在其他地方被称为“邪恶”:http://ziade.org/2008/01/08/syssetdefaultencoding-is-evil/ - 请不要使用它。 - anarcat
1
这是补丁的圣杯。 - Alastair McCormack

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