简体   繁体   English

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

[英]How to set preferred encoding in WSGI to UTF-8

Feeling a bit crazy here.感觉这里有点疯狂。 I've got Apache set up with mod_wsgi, but I can't get the encoding to work properly.我已经用 mod_wsgi 设置了 Apache,但我无法让编码正常工作。 I have:我有:

  • tested that mod_wsgi is running in daemon mode测试 mod_wsgi 是否在守护进程模式下运行
  • read Graham Dumpleton's blog post about setting up the lang and locale settings for the WSGIDaemonProcess directive.阅读Graham Dumpleton 的博客文章,了解为WSGIDaemonProcess指令设置langlocale设置。
  • created a minimal test that seems to demonstrate the issue创建了一个似乎可以证明问题的最小测试
# 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'

My WSGI configs look like this:我的 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

When I log into the server and start python in the terminal, this line works fine, but it fails when it runs via mod_wsgi :当我登录服务器并在终端中启动python时,这条线工作正常,但是当它通过 mod_wsgi 运行时失败

from reporters_db import REPORTERS

All that line does is import a json file that has some utf-8 content in it.该行所做的只是导入一个包含一些 utf-8 内容的 json 文件。 Here's the code behind that import:这是该导入背后的代码:

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)

Since the json call above doesn't have the encoding specified, it uses ASCII and fails:由于上面的 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)

How can I tell it (and the rest of my codebase) to use utf-8 like sane adults?我如何告诉它(以及我的代码库的其余部分)像理智的成年人一样使用 utf-8?


Edit 1编辑 1

Perhaps it is important to mention that I'm running apache with the following command:也许值得一提的是,我正在使用以下命令运行 apache:

exec apache2ctl -D FOREGROUND "$@"

I thought that would source the /etc/apache2/envvars file, so I appended the following to that file:我认为这会获取/etc/apache2/envvars文件,所以我在该文件中附加了以下内容:

export LANG="en_US.UTF-8"

And I tried tweaking my startup command to:我尝试将启动命令调整为:

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

I was hopeful, but no.我充满希望,但没有。 Still no progress.仍然没有进展。

Well, I finally figured this out by searching for every time Graham Dumpleton mentioned the word "lang" on the Internet.好吧,我终于通过搜索 Graham Dumpleton 每次在 Internet 上提到“lang”这个词时发现了这一点。 That eventually turned up this thread , which mentioned that it was possible to not have a locale installed.最终出现了这个线程,其中提到可能没有安装语言环境。 I was able to check that by running locale -a inside my Ubuntu Docker image, which revealed:我可以通过在我的 Ubuntu Docker 映像中运行locale -a来检查这一点,结果显示:

locale -a
C
C.UTF-8
POSIX

So that's the issue!所以这就是问题! mod_wsgi doesn't know what I'm asking for when I ask for en_US.utf-8 , and it doesn't throw an error either.当我要求en_US.utf-8时, mod_wsgi不知道我在要求什么,它也不会引发错误。 Swapping my settings to instead be set to C.UTF-8 fixed this immediately.将我的设置交换为C.UTF-8立即解决了这个问题。

I'm running a slim docker image, so that must be why I lack locales.我正在运行一个苗条的 docker 映像,所以这一定是我缺少语言环境的原因。 I also don't have a file at /etc/default/locale that a lot of other answers in this general area refer to.我在/etc/default/locale也没有这个一般区域中的许多其他答案所引用的文件。

I've filed this as a bug .我已将此作为错误提交。

I had a similar UnicodeDecodeError issue when parsing a yaml file containing Unicode characters on Debian 11, Apache2, mod_wsgi.在 Debian 11、Apache2、mod_wsgi 上解析包含 Unicode 字符的 yaml 文件时,我遇到了类似的 UnicodeDecodeError 问题。

It was enough to set WSGIDaemonProcess locale to C.UTF-8, then the error went.将 WSGIDaemonProcess 语言环境设置为 C.UTF-8 就足够了,然后错误就消失了。 This single line changed in my /etc/apache2/sites-available/000-default.conf这一行在我的 /etc/apache2/sites-available/000-default.conf 中发生了变化

     WSGIDaemonProcess my_app locale='C.UTF-8'

In the question, mlissner mentioned a bunch of settings tried, but those were not needed for me.在问题中,mlissner 提到了一些尝试过的设置,但我不需要这些设置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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