【问题标题】:uWSGI unable to write unicode data in log file redirected from Python's stdout logginguWSGI 无法在从 Python 的标准输出日志重定向的日志文件中写入 unicode 数据
【发布时间】:2022-03-11 12:30:31
【问题描述】:

我正在使用 uWSGI (2.0.11.2) 和 Python (3.4.3) 在 Ubuntu 14.04 上为我的 Pyramid (1.5.7) 应用程序提供服务。我注意到我的 uWSGI 日志中出现与 unicode 解码相关的错误:

#
# one of the situations when exception is raised is
# when SQLAlchemy (which has set INFO logging level)
# tries to write an SQL statement containing unicode charater
# into log file
#
2016-02-26 16:01:38,734 INFO  [sqlalchemy.engine.base.Engine][b'uWSGIWorker5Core0'] BEGIN (implicit)
2016-02-26 16:01:38,735 INFO  [sqlalchemy.engine.base.Engine][b'uWSGIWorker5Core0'] SELECT * FROM staging WHERE company_name = %(company_name_1)s AND time = %(time_1)s AND ship_name = %(ship_name_1)s
# exact place (missing line) where SQLAlchemy is trying to print out
# query parameters, which in this case include unicode character
--- Logging error ---
Traceback (most recent call last):
  File "/usr/lib/python3.4/logging/__init__.py", line 980, in emit
    stream.write(msg)
UnicodeEncodeError: 'ascii' codec can't encode character '\xfa' in position 132: ordinal not in range(128)
Call stack:
  File "/home/mk/.virtualenvs/api/lib/python3.4/site-packages/sqltap/wsgi.py", line 42, in __call__
    return self.app(environ, start_response)
  File "/home/mk/.virtualenvs/api/lib/python3.4/site-packages/pyramid/router.py", line 242, in __call__
    response = self.invoke_subrequest(request, use_tweens=True)
  #
  # the stack continues...
  # full stack here -> https://bpaste.net/show/8e12af790372
  #
  File "/home/mk/.virtualenvs/api/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 1010, in _execute_clauseelement
    compiled_sql, distilled_params
  File "/home/mk/.virtualenvs/api/lib/python3.4/site-packages/sqlalchemy/engine/base.py", line 1100, in _execute_context
    sql_util._repr_params(parameters, batches=10)
Unable to print the message and arguments - possible formatting error.
Use the traceback above to help find the error.

我还注意到,将相同的行写入 Pyramid 生成的日志文件(不涉及 uWSGI)工作得非常好,没有任何错误,并且正确插入了 unicode 字符。

我正在使用这个命令运行 uWSGI:

/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals

vassals 文件夹中,我从我的 Pyramid 应用程序中符号链接了 uWSGI 配置,它看起来像这样:

[uwsgi]

host = %h
username = mk
project_name = api
project_root = /shared/projects/python/%(project_name)

env = PYTHONIOENCODING=UTF-8

; this env var is generated based on host name
env = APP_INI_FILE=develop.ini

; folders config
home_folder = /home/%(username)
virtualenv_folder = %(home_folder)/.virtualenvs/%(project_name)
logs_folder = %(home_folder)/logs/%(project_name)
chdir = %(project_root)
socket = %(project_root)/%(project_name).sock
pidfile = %(project_root)/%(project_name).pid
virtualenv = %(virtualenv_folder)
daemonize = %(logs_folder)/uwsgi.log

; core stuff
master = true
vacuum = true
processes = 5
enable-threads = true

; socket conf
chmod-socket = 666  # invoking the One
chown-socket = %(username)
uid = %(username)
gid = %(username)

; log conf
log-reopen = true
logfile-chown = %(username)
logfile-chmod = 644

; app conf
module = wsgi:application
harakiri = 120
max-requests = 500
post-buffering = 1
paste = config:%p
paste-logger = $p

定义所有日志记录的 Pyramid 配置文件如下所示:

###
# app configuration
# http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/narr/environment.html
###

[DEFAULT]
home_dir = /home/mk

[app:main]
use = egg:api

pyramid.reload_templates = false
pyramid.debug_authorization = false
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en

sqlalchemy.url = postgresql://XXX:YYY@12.13.14.15:5432/ze_database?client_encoding=utf8

[server:main]
use = egg:waitress#main
host = 0.0.0.0
port = 6543

###
# logging configuration
# http://docs.pylonsproject.org/projects/pyramid/en/1.5-branch/narr/logging.html
###

[loggers]
keys = root, sqlalchemy

[handlers]
keys = console, debuglog

[formatters]
keys = generic, short

[logger_root]
level = DEBUG
handlers = console, debuglog

[logger_sqlalchemy]
level = INFO
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
# "level = DEBUG" logs SQL queries and results.
# "level = WARN" logs neither.  (Recommended for production systems.)

[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = DEBUG
formatter = generic

[handler_debuglog]
class = handlers.RotatingFileHandler
args = ('%(home_dir)s/logs/api/pyramid_debug.log', 'a', 1024000000, 10)
level = DEBUG
formatter = generic

[formatter_generic]
format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s

[formatter_short]
format = %(asctime)s %(message)s

最后,我的 Pyramid 的 wsgi.py 文件非常简单:

import os
from pyramid.paster import get_app, setup_logging

here = os.path.dirname(os.path.abspath(__file__))
conf = os.path.join(here, os.environ.get('APP_INI_FILE'))  # APP_INI_FILE variable is set in uwsgi.ini
setup_logging(conf)

application = get_app(conf, 'main')

本质上,我将应用程序的日志重定向到stderr(或stdout,据我所知,它们都是一样的),同时我还将它写在一个单独的文件中(pyramid_debug.log) . stderr 在我的例子中是 uWSGI 守护进程的日志文件,这就是错误发生的地方。

虽然LC_ALL 和相关变量在系统上设置为en_EN.UTF-8,但我也尝试使用各种与本地化相关的环境变量并在我的 Pyramid 的 wsgi 应用程序中明确设置它们,但运气不佳 - 例如,在 uWSGI 配置中仅设置 PYTHONIOENCODING=UTF-8 变量解决了我本地机器上的问题,但部署后无法解决服务器上的问题。

我的明显问题是 - 在这种情况下如何正确处理 uWSGI 在日志文件中写入 unicode 字符?

【问题讨论】:

    标签: python logging unicode pyramid uwsgi


    【解决方案1】:

    编辑 File "/usr/lib/python3.4/logging/__init__.py", line 980 并更改

    stream.write(msg)
    

    stream.write(msg.encode('utf-8'))
    

    流类型的更改很可能不会破坏您的 UTF-8 编码功能,但实际上是因为 Pythonics。 (似乎无论世界如何大声疾呼“UTF-8”,Python 在这件事上都忽略了所有人。)

    例如,如果您正在处理文件,您尝试过的所有环境变量都会被忽略:

    # test.py
    import sys
    sys.stdout.write(u'\u00f6\n')
    

    测试:

    max% python test.py
    ö
    max% python test.py > f
    Traceback (most recent call last):
      File "test.py", line 2, in <module>
        sys.stdout.write(u'\u00f6\n')
    UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 0: ordinal not in range(128)
    

    【讨论】:

    • 这是发生在我身上的 wsgi +烧瓶。我不确定我是否了解情况。大家在使用uwsgi的时候是不是有这样的日志记录问题?
    【解决方案2】:

    设置 LANG=C.UTF-8 对我有用。

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案3】:

    尝试将您的环境变量 PYTHONIOENCODING 设置为 utf-8。这将使文本文件的默认编码为 UTF-8 而不是 ASCII。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-30
      • 2016-10-07
      • 2011-05-19
      • 2014-11-30
      • 2019-03-30
      • 2010-10-14
      相关资源
      最近更新 更多