编码问题困惑(Shell与重音)

5 投票
2 回答
1085 浏览
提问于 2025-04-17 05:33

我在处理编码方面遇到了一些麻烦。 我使用的版本是:

Python 2.7.2+(默认,2011年10月4日,20:03:08) [GCC 4.6.1] 在 linux2 上

我有一些带重音的字符,比如 é 和 à。 我的脚本使用的是 utf-8 编码。

#!/usr/bin/python
# -*- coding: utf-8 -*-

用户可以通过 raw_input() 输入字符串。

def rlinput(prompt, prefill=''):
    readline.set_startup_hook(lambda: readline.insert_text( prefill))
    try:
        return raw_input(prompt)
    finally:
        readline.set_startup_hook()

这个输入是在主循环的“伪”命令行中进行的。

while to_continue : 
    to_continue, feedback = action( unicode(rlinput(u'todo > '),'utf-8') )
    os.system('clear')
    print T, u"\n" + feedback

数据以 pickle 格式存储在文件中。

我设法让应用程序正常工作,但最后却遇到了一些愚蠢的问题,比如:

核心文件:

class Task()
...
def __str__(self):
    r = (u"OK" if self._done else u"A faire").ljust(8) + self.getDesc()
    return r.encode('utf-8')

在 shell 文件中:

feedback = jaune + str(t).decode('utf-8') + vert + u" supprimée"

这让我意识到我可能在编码/解码方面完全搞错了。 所以我尝试直接在 rlinput 中解码,但失败了。 我在 StackOverflow 上读了一些帖子,还重新阅读了 http://docs.python.org/library/codecs.html。 在等待我的 Python 书到来时,我感到很迷茫 :/

我想代码中可能有很多问题,但我在这里的问题仅与编码有关。 你可以在这里找到代码:(大部分注释是法语,抱歉,这是个人使用,我还是个初学者,你还需要 yapsy - http://yapsy.sourceforge.net/) (然后配置路径,在 py_todo 中:./todo_shell.py):http://bit.ly/rzp9Jm

2 个回答

0

正如@wberry建议的,我检查了编码:没问题。

$ file --mime-encoding todo_shell.py task.py todo.py
todo_shell.py: utf-8
task.py:       utf-8
todo.py:       utf-8
$ echo $LANG
fr_FR.UTF-8
$ python -c "import sys; print sys.stdin.encoding"
UTF-8

根据@eryksun的建议,我解码了用户输入的内容(还有之前提交的字符串也进行了编码)(如果我没记错的话,这解决了一些问题)(稍后会深入测试):

def rlinput(prompt, prefill=''):
readline.set_startup_hook(lambda: readline.insert_text( prefill.encode(sys.stdin.encoding) ))
try:
    return raw_input( prompt ).decode( sys.stdin.encoding )
finally:
    readline.set_startup_hook()

我仍然有一些问题,但我的问题没有定义清楚,所以我无法得到明确的答案。现在我感觉不那么迷茫了,也有了搜索的方向。谢谢你!

补充:我把str方法换成了unicode,这解决了一些(可能是所有的)问题。

感谢@eryksun的建议。(这个链接对我有帮助:Python __str__ 和 __unicode__ 的区别

2

在所有Unix系统中,标准输入和输出都是基于字节的。这就是为什么你需要调用unicode函数来获取它们的字符字符串。解码错误表示输入的字节不是有效的UTF-8格式。

简单来说,问题在于你假设输入是UTF-8编码,但这并没有保证。你可以通过将unicode调用中的编码改为'ISO-8859-1',或者把你的终端模拟器的字符编码改为UTF-8来确认这一点。(Putty在“Translation”菜单中支持这个选项。)

如果以上实验确认了这个问题,那么你的挑战就是支持用户的本地设置,并推测出正确的编码,或者让用户在命令行参数或配置中声明编码。$LANG环境变量是你在没有明确声明的情况下能做的最好的选择,但我发现它并不是一个很好的指示所需字符编码的方式。

撰写回答