简体   繁体   English

如何在Apache / WSGI下控制Python的标准输出编码

[英]How to control Python's stdout encoding under Apache/WSGI

I'm writing a Django app, and it prints Unicode to stdout . 我正在编写Django应用,它将Unicode stdoutstdout 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 . 我也试着设置LANGLC_ALLLC_CTYPEen_US.UTF-8使用SetEnvPassEnv

  • 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-8WSGIDaemonProcess指令中。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM