Python3 默认编码 UnicodeDecodeError,使用 Apache WSGI 时出现 ascii 错误

8
import locale
prefered_encoding = locale.getpreferredencoding()
prefered_encoding 'ANSI_X3.4-1968'

我正在使用一个名为"inginious"的框架,它使用"web.py"来渲染模板。请参考inginiousweb.py 了解更多信息。
web.template.render(os.path.join(root_path, dir_path),
                                   globals=self._template_globals,
                                   base=layout_path)

渲染在我的本地主机上可以正常工作,但在我的暂存服务器上无法正常工作。

它们都运行python3。我发现web.py只在Python2中强制执行utf-8编码(这不在我的控制范围内)。

def __str__(self):
    self._prepare_body()
    if PY2:
        return self["__body__"].encode('utf-8')
    else:
        return self["__body__"]

以下是堆栈跟踪信息:

t = self._template(name),
File "/lib/python3.5/site-packages/web/template.py", line 1028, in _template,
self._cache[name] = self._load_template(name),
File "/lib/python3.5/site-packages/web/template.py", line 1016, in _load_template
return Template(open(path).read(), filename=path, **self._keywords)
File "/lib64/python3.5/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 83: ordinal not in range(128),

我的HTML包含希伯来字符,以下是一个小例子:

<div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal">&times;</button>
                        <h4 class="modal-title feedback-modal-title">
                            חישוב האיברים הראשונים בסדרה של איבר ראשון חיובי ויחס שלילי:
                            <span class="red-text">אי הצלחה</span>

我这样打开它:

open('/path/to/feedback.html').read()

编码失败的那一行是包含希伯来字符的那一行。

我尝试在~/.bashrc中设置了一些环境变量:

export PYTHONIOENCODING=utf8
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8

在用户centos下:

巧妙的框架安装在python3.5 site-packages下的pip中,并由用户apache下的apache服务器提供服务。

尝试在代码中设置环境变量(在应用程序的初始化期间),以便apache WSGI能够意识到它们。

import os 
os.environ['LC_ALL'] = 'en_US.UTF-8'
os.environ['LANG'] = 'en_US.UTF-8'
os.environ['LANGUAGE'] = 'en_US.UTF-8'

我使用setenv方法编辑了/etc/httpd/conf/httpd.conf文件:

SetEnv LC_ALL en_US.UTF-8
SetEnv LANG en_US.UTF-8
SetEnv LANGUAGE en_US.UTF-8
SetEnv PYTHONIOENCODING utf8

我尝试使用sudo service httpd restart来重新启动,但仍然没有成功。

我的问题是,最佳实践是什么?我知道有一些hack的方法,但我想要了解根本原因以及如何解决。

谢谢!


ANSI_X3.4-1968 等同于 ASCII - Martijn Pieters
你需要向我们展示完整的回溯信息以及如何重现它。 - Martijn Pieters
哎呀,web.py 对读取模板文件的处理不是很好,它应该明确指定编码方式。说实话,这相当愚蠢。你可以通过使用 HTML 实体来解决非 ASCII 文本的问题,但我的个人建议是放弃 web.py,转而使用 Flask 或 Django(它们的模板处理在真正的 Python 3 部署中更加经过考验)。 - Martijn Pieters
尝试了一下,没有成功。编辑了问题。请看“尝试设置环境变量”。这是正确的位置吗?还是我应该将其放在 Apache 设置文件的某个地方。如果是的话,我不知道该文件的默认位置。 - WebQube
让我们在聊天中继续这个讨论 - WebQube
显示剩余6条评论
2个回答

1

一种 Python 2+3 的解决方案为:

import io

with io.open(file_path, mode='r', encoding='utf8') as f:
     text = f.read()

请参阅 io.open 的文档。

1
最终在阅读文件时找到了答案,将其从

更改为
open('/path/to/feedback.html').read()

to

import codecs
with codecs.open(file_path,'r',encoding='utf8') as f:
     text = f.read()

如果有更通用的方法可行,我会接受他的答案。


并不完全准确。在Python3中,“在文本模式下,如果没有指定编码,则使用的编码与平台有关:调用locale.getpreferredencoding(False)以获取当前语言环境的编码”。换句话说,您上面所做的将起作用,但真正的问题是 locale.getpreferredencoding(False) 没有像您想要的那样返回 utf-8。这是来自 python3文档 的内容。 - mlissner

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