解码/编码问题

时间:2012-06-03 15:16:27

标签: python unicode encoding

我目前在Linux(Ubuntu)下编码/编码存在严重问题。我之前从未需要处理过,所以我不知道为什么这实际上不起作用!

我正在从 / usr / share / applications / 解析*.desktop个文件,并通过HTTPServer提取Web浏览器中显示的信息。我正在使用jinja2进行模板化。

首先,我在致电UnicodeDecodeError时收到jinja2.Template.render(),其中说

utf-8 cannot decode character XXX at position YY [...]

所以我创建了来自appfind - 模块(解析*.desktop文件)的所有值,只返回unicode-strings。

到目前为止,这个地方的问题已经解决了,但是在某些时候我正在写一个函数返回到BaseHTTPServer.BaseHTTTPRequestHandler.wfile插槽的字符串,我不能修复这个错误,无论编码是什么使用

此时,写入wfile的字符串来自jinja2.Template.render(),afaik返回一个unicode对象。

奇怪的是,它正在处理我的 Ubuntu 12.04 LTS ,而不是我朋友的 Ubuntu 11.04 LTS 。但是,这可能不是原因。他有更多的应用程序,也许他们会在*.desktop文件中使用编码来引发错误。

但是,我在*.desktop文件中正确检查了编码:

data = dict(parser.items('Desktop Entry'))

try:
    encoding = data.get('encoding', 'utf-8')
    result = {
        'name':       data['name'].decode(encoding),
        'exec':       DKENTRY_EXECREPL.sub('', data['exec']).decode(encoding),
        'type':       data['type'].decode(encoding),
        'version':    float(data.get('version', 1.0)),
        'encoding':   encoding,
        'comment':    data.get('comment', '').decode(encoding) or None,
        'categories': _filter_bool(data.get('categories', '').
                                        decode(encoding).split(';')),
        'mimetypes':  _filter_bool(data.get('mimetype', '').
                                        decode(encoding).split(';')),
    }

# ...

有人可以告诉我如何修复此错误吗?我已经读过关于SO的答案,我应该总是使用unicode(),但实施起来会非常痛苦,而且我不认为在写入wfile时会解决问题吗? / p>

谢谢,
尼古拉斯

4 个答案:

答案 0 :(得分:3)

这可能很明显,但无论如何:wfile是一个普通的字节流:写入的所有内容必须是unicode.encode():ed。

阅读OP,我不清楚究竟是什么,正在进行中。但是,有一些技巧可以帮助你,我发现有助于调试编码问题。如果这是你早已超越的东西,我会提前道歉。

    文件中的
  • cat -v会将所有非ascii字符输出为'^ X',这是我发现的唯一一种可以确定文件编码方式的简单方法。 UTF-8非ascii字符是多字节的。这意味着它们将是多个'^'的序列 - cat -v的条目。

  • 根据我的经验,Shell环境(LC_ALL等)是导致问题的最常见原因。确保您的系统具有包含UTF-8的语言环境,例如:拉丁-1可用。 始终将您的LC_ALL设置为明确命名编码的区域设置,例如LC_ALL=sv_SE.iso88591

  • 在bash和zsh中,您可以运行具有该命令的特定环境更改的命令,如下所示:

    $ LC_ALL=sv_SE.utf8 python ./foo.py
    

    这使得测试比导出不同的语言环境容易得多,并且不会污染shell。

  • 不要假设你内部有unicode字符串。编写断言语句,验证字符串是unicode。

    assert isinstance(foo, unicode)
    
  • 了解如何识别您正在使用的编码中的常见字符的错误/误传版本。例如。 '\ xe4'是latin-1 a diaresis而'ä'是两个UTF-8字节,构成一个diaresis,错误地用latin-1表示。我发现知道这种gorp可以大大减少调试编码问题。

答案 1 :(得分:1)

您需要对字节字符串和Unicode字符串采取严格的方法。这解释了一切:Pragmatic Unicode, or, How Do I Stop the Pain?

答案 2 :(得分:0)

默认情况下,当python遇到unicde的编码问题时,会抛出错误。但是,可以修改此行为,例如,如果错误是预期的或不重要的。

假设您正在两个作为ascii超集的unicode页面之间进行转换。两者都有相同的字符,但没有一对一的对应关系。因此,您可能希望忽略错误。

为此,请使用编码功能中的errors变量。

mystring = u'This is a test'
print mystring.encode('utf-8', 'ignore')
print mystring.encode('utf-8', 'replace')
print mystring.encode('utf-8', 'xmlcharrefreplace')
print mystring.encode('utf-8', 'backslashreplace')

如果在读/写时使用了错误的编码,unicode会有很多问题。确保在获得unicode字符串后,将其转换为unicode desired by jinja2的形式。

如果这没有帮助,您能否添加您看到的第二个错误,可能还有一个代码段来澄清正在发生的事情?

答案 3 :(得分:0)

尝试在代码段中的所有匹配项中使用.encode(encoding)代替.decode(encoding)