【问题标题】:How to control Python's stdout encoding under Apache/WSGIApache/WSGI下如何控制Python的stdout编码
【发布时间】:2017-12-23 21:21:40
【问题描述】:

我正在编写一个 Django 应用程序,它将 Unicode 打印到 stdout。它在开发服务器上完美运行,但使用 Apache 和 modwsgi 我得到UnicodeEncodeError: 'ascii' codec can't encode characters ...

因此,stdout 编码被强制为 ASCII。我找到了许多解决方案,所有这些似乎都应该根据文档工作,但没有一个对我有用:

  • 我尝试使用SetEnv 指令将PYTHONIOENCODING 变量设置为utf-8

  • 我还尝试使用SetEnvPassEnvLANGLC_ALLLC_CTYPE 设置为en_US.UTF-8

  • 由于我的 Apache 服务器在 systemd 下运行,我尝试使用服务文件中的 Environment= 指令设置变量。

  • 最后,我尝试将lang=en_US.UTF-8 locale=en_US.UTF-8 添加到WSGIDaemonProcess 指令中。

在环境中可以看到变量(例如反映在调试模式下的 Django 错误页面上),但错误仍然存​​在。

为什么这些东西不起作用,我该怎么办?在 Apache 外部正常工作的代码中覆盖 stdout 或手动编码所有内容都不是正确的方法。

错误发生在普通的print 语句中。这是引发错误的整个视图:

def test(request):
    import locale
    print locale.getdefaultlocale()
    print locale.getpreferredencoding()

    s = u'привет'
    print s
    return s

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)

当我打印sys.stdout 本身时,我发现它实际上是一个mod_wsgi.Log 对象。在 WSGI 文件中,我所有的日志记录是:

logging.basicConfig(stream=sys.stderr)

版本: 蟒蛇2.7.14, 阿帕奇 2.4.29, mod_wsgi 4.5.20 在 Arch Linux 上

【问题讨论】:

  • from __future__ import unicode_literals 怎么样?对你来说是一种解决方法吗?
  • 虽然很老了,但这些天我们面临着同样的问题。你想清楚了吗?

标签: python django apache encoding mod-wsgi


【解决方案1】:

前两个不会做任何事情,因为SetEnv 只设置每个请求的 WSGI 环境,而不是进程变量。

在 WSGIDaemonProcess 上添加语言/语言环境在大多数情况下应该可以工作,前提是您实际上是在守护程序模式下运行的东西。它不适用于嵌入式模式。

您是否确认您实际上是在守护程序模式下运行。

【讨论】:

  • 谢谢!我以前看过你的帖子。有趣的是:你写(环境变量):“它们需要在初始 Apache 进程启动的环境中设置”。由于我的 Apache 服务器在 systemd 下运行,我刚刚尝试的是在插入式 override.conf 中使用 Environment= 指令来设置 LANGLC_ALL。没有运气。
  • P.S.通过第二个链接中的测试application,我看到了我在 Apache 配置中使用WSGIProcessGroup 指令设置的(非空)mod_wsgi.process_group 值。
  • 所以在 systemd 配置文件中设置 PYTHONIOENCODING 也没有帮助?你能看到在 WSGI 应用程序中设置的环境变量吗?
  • 是的。 PYTHONIOENCODING 已设置,但错误仍然存​​在。
  • locale.getdefaultlocale()locale.getpreferredencoding() 得到什么,如 blog.dscpl.com.au/2014/09/… 中所述
【解决方案2】:

这是一个改变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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-30
    • 1970-01-01
    • 2018-03-24
    • 1970-01-01
    • 2011-03-27
    • 1970-01-01
    • 2016-12-23
    • 2016-12-19
    相关资源
    最近更新 更多