[英]How to control Python's stdout encoding under Apache/WSGI
I'm writing a Django app, and it prints Unicode to stdout
. 我正在编写Django应用,它将Unicode
stdout
到stdout
。 It works perfectly on the development server, but with Apache and modwsgi I get UnicodeEncodeError: 'ascii' codec can't encode characters ...
. 它可以在开发服务器上完美运行,但是使用Apache和modwsgi时,我得到
UnicodeEncodeError: 'ascii' codec can't encode characters ...
So, the stdout encoding is forced to ASCII. 因此,stdout编码被强制为ASCII。 I've found a number of solutions, all of which seem like they should work according to documentation, but none work for me:
我发现了许多解决方案,所有这些解决方案似乎都应该根据文档进行工作,但对我而言却无济于事:
I tried setting the PYTHONIOENCODING
variable to utf-8
, using the SetEnv
directive. 我试过设置
PYTHONIOENCODING
变量utf-8
使用SetEnv
指令。
I also tried setting LANG
, LC_ALL
, LC_CTYPE
to en_US.UTF-8
using SetEnv
and PassEnv
. 我也试着设置
LANG
, LC_ALL
, LC_CTYPE
到en_US.UTF-8
使用SetEnv
和PassEnv
。
Since my Apache server is running under systemd
, I tried setting the variables using Environment=
directives in the service file. 由于我的Apache服务器在
systemd
下运行,因此我尝试使用服务文件中的Environment=
指令设置变量。
Finally, I tried adding lang=en_US.UTF-8 locale=en_US.UTF-8
to the WSGIDaemonProcess
directive. 最后,我尝试将
lang=en_US.UTF-8 locale=en_US.UTF-8
到WSGIDaemonProcess
指令中。
The variables are seen in the environment (reflected eg on Django error pages in debug mode), but the error still occurs. 这些变量在环境中可见(例如,在调试模式下的Django错误页面上反映出来),但是仍然会发生错误。
Why don't these things work and what should I do? 这些东西为什么不起作用,我该怎么办? Overriding
stdout
in the code that works fine outside Apache or encoding everything manually doesn't feel like the right approach. 在Apache外部可以正常工作的代码中覆盖
stdout
或手动对所有内容进行编码都不是正确的方法。
The error occurs at a plain print
statement. 该错误发生在普通
print
语句上。 Here's the entire view that raises the error: 这是引发错误的整个视图:
def test(request):
import locale
print locale.getdefaultlocale()
print locale.getpreferredencoding()
s = u'привет'
print s
return s
Apache error log: Apache错误日志:
('en_US', 'UTF-8')
UTF-8
Internal Server Error: /app/testview/
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py", line 249, in _legacy_get_response
response = self._get_response(request)
File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/web/my_site/my_app/views.py", line 964, in test
print s
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
When I print sys.stdout
itself, I see that it's actually a mod_wsgi.Log
object. 当我打印
sys.stdout
本身时,我看到它实际上是一个mod_wsgi.Log
对象。 In the WSGI file, all I have for logging is: 在WSGI文件中,我要做的记录是:
logging.basicConfig(stream=sys.stderr)
Versions: Python 2.7.14, Apache 2.4.29, mod_wsgi 4.5.20 on Arch Linux 版本:Arch Linux上的Python 2.7.14,Apache 2.4.29,mod_wsgi 4.5.20
The first two will not do anything as SetEnv
only sets per request WSGI environ, not process variables. 前两个不会做任何事情,因为
SetEnv
仅针对每个请求设置WSGI环境,而不设置过程变量。
Adding lang/locale on WSGIDaemonProcess should work in most cases provided you are actually running things in daemon mode. 在大多数情况下,只要您实际上是在守护程序模式下运行事物,就可以在WSGIDaemonProcess上添加lang / locale。 It will not work for embedded mode.
它不适用于嵌入式模式。
Have you verified you are actually running in daemon mode. 您是否已验证自己实际上是在守护程序模式下运行。
Here is a solution that changed HTTPD_LANG=${HTTPD_LANG-"en_US.utf8"}
这是更改
HTTPD_LANG=${HTTPD_LANG-"en_US.utf8"}
的解决方案
$ cat -n /etc/init.d/httpd | grep HTTPD_LANG
34 HTTPD_LANG=${HTTPD_LANG-"en_US.utf8"}
59 LANG=$HTTPD_LANG daemon --pidfile=${pidfile} $httpd $OPTIONS
85 if ! LANG=$HTTPD_LANG $httpd $OPTIONS -t >&/dev/null; then
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.