如何将WSGI中的首选编码设置为UTF-8 编辑1

问题描述

在这里有点疯狂。我已经用mod_wsgi设置了Apache,但是我无法使编码正常工作。我有

  • 测试了mod_wsgi是否在守护程序模式下运行
  • 阅读Graham Dumpleton's blog post有关为lang指令设置localeWsgiDaemonProcess设置的信息。
  • 创建了一个似乎可以证明问题的最小测试
# I recompiled the mod_wsgi file to get the Python version correct
sys.version = '3.8.6 (default,Sep 24 2020,21:54:23) \n[GCC 8.3.0]'
sys.prefix = '/usr/local'
sys.path = ['/usr/local/lib/python38.zip','/usr/local/lib/python3.8','/usr/local/lib/python3.8/lib-dynload','/usr/local/lib/python3.8/site-packages','/usr/local/src/scorched']

# This seems to be a timing thing? Not sure,but possibly problematic
locale.getlocale() = (None,None)
# This was fixed by setting lang or locale (not sure which)
locale.getdefaultlocale() = ('en_US','UTF-8')
sys.getdefaultencoding() = 'utf-8'

# These seem like a problem...
sys.getfilesystemencoding() = 'ascii'
locale.getpreferredencoding(False): 'ANSI_X3.4-1968'

# It's daemon mode
mod_wsgi.process_group = 'cl'

我的Wsgi配置如下:

    WsgiScriptAlias / /opt/courtlistener/docker/apache/wsgi-configs/python_version_test.py
    WsgiDaemonProcess cl \
      threads=10 \
      processes=64 \
      python-path=/usr/local/lib/python3.8/site-packages/ \
      lang='en_US.UTF-8' \
      locale='en_US.UTF-8'
    WsgiProcessGroup cl
    WsgiApplicationGroup %{GLOBAL}
    WsgiPassAuthorization On

当我登录服务器并在终端中启动python时,此行工作正常,但通过mod_wsgi运行时失败

from reporters_db import REPORTERS

该行所做的只是导入一个其中包含一些utf-8内容的json文件。这是该导入背后的代码

db_root = os.path.dirname(os.path.realpath(__file__))
with open(os.path.join(db_root,"data","reporters.json")) as f:
    REPORTERS = json.load(f,object_hook=datetime_parser)

由于上述json调用未指定编码,因此使用ASCII并失败:

 Traceback (most recent call last):
   File "/opt/courtlistener/docker/apache/wsgi-configs/python_version_test.py",line 6,in <module>
     from reporters_db import REPORTERS
   File "/usr/local/lib/python3.8/site-packages/reporters_db/__init__.py",line 22,in <module>
     REPORTERS = json.load(f,object_hook=datetime_parser)
   File "/usr/local/lib/python3.8/json/__init__.py",line 293,in load
     return loads(fp.read(),File "/usr/local/lib/python3.8/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 441720: ordinal not in range(128)

我如何告诉它(以及我的代码库的其余部分)像理智的成年人那样使用utf-8?


编辑1

也许值得一提的是,我正在使用以下命令运行apache:

exec apache2ctl -D FOREGROUND "$@"

我认为这将成为/etc/apache2/envvars文件的来源,因此我在文件中附加了以下内容

export LANG="en_US.UTF-8"

然后我尝试将启动命令调整为:

LANG="en_US.UTF-8" exec apache2ctl -D FOREGROUND "$@"

我充满希望,但没有。仍然没有进展。

解决方法

好吧,我终于通过搜索Graham Dumpleton每次在互联网上提及“ lang”一词来弄清这一点。最终出现了this thread,其中提到可能没有安装语言环境。我可以通过在Ubuntu Docker映像中运行locale -a进行检查,该映像显示:

locale -a
C
C.UTF-8
POSIX

这就是问题所在! mod_wsgi不知道我要的是什么en_US.utf-8,它也不会抛出错误。将我的设置交换为C.UTF-8即可立即解决。

我正在运行一个苗条的docker映像,所以这一定是为什么我缺少语言环境的原因。我在/etc/default/locale上也没有该一般领域中许多其他答案所引用的文件。

我将其归档为a bug