Celery 无法在“utf-8”中记录字符串错误。 Unicode解码错误

Posted

技术标签:

【中文标题】Celery 无法在“utf-8”中记录字符串错误。 Unicode解码错误【英文标题】:Celery can't log string errors in 'utf-8'. UnicodeDecodeError 【发布时间】:2019-05-13 14:54:37 【问题描述】:

有时我需要用俄语的参数创建错误。例如:

raise FooError(c_(u'Task %(name)s'), params = 'name': "курочка")

然后我有这个错误:

Traceback (most recent call last):
  File "/usr/lib/python2.7/logging/__init__.py", line 868, in emit
    msg = self.format(record)
  File "/usr/lib/python2.7/logging/__init__.py", line 741, in format
    return fmt.format(record)
  File "/usr/lib/python2.7/logging/__init__.py", line 465, in format
    record.message = record.getMessage()
  File "/usr/lib/python2.7/logging/__init__.py", line 329, in getMessage
    msg = msg % self.args
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd0 in position 0: ordinal not in range(128)

我用:

Python 2.7.15rc1;

芹菜 3.1.19;

django-celery 3.1.17;

Django 1.11.2.

您可以重现该错误:

import logging
from logging import getLogger 
l = getLogger()
handler = logging.FileHandler('/tmp/fh')
l.addHandler(handler)
l.log(50, u'Task 1')
l.log(50, u'Task %(name)s', 'name': "курочка")

我认为芹菜有问题。如果您打开<your part>/lib/python2.7/site-packages/celery/worker/job.py,您将能够看到 100-124 行。我们将在其中传递参数的已形成消息,例如:

#: Format string used to log task failure.
error_msg = """\
    Task %(name)s[%(id)s] %(description)s: %(exc)s
"""

并且预计数据会是英文布局中的字符串(см.function_log_error(<...>)):

...
exception, traceback, exc_info, internal, sargs, skwargs = (
    safe_repr(eobj),
    safe_str(einfo.traceback),
    einfo.exc_info,
    einfo.internal,
    safe_repr(self.args),
    safe_repr(self.kwargs),
)
…

但是 resp 在我的异常中只返回带有俄语单词的 str 并且都失败了。所以是Celery的问题。

我也知道我的 LANG="ru_RU.UTF-8"。我知道: sys.getdefaultencoding() 返回 «ascii», 如果我写:

reload(sys)
sys.setdefaultencoding(«UTF-8»)

它将解决我的问题,我将收到俄语信息。

但我想有其他解决方案,因为这个决定没有得到我的批准。

【问题讨论】:

# -*- coding: utf-8 -*- ? 我在标准python文件以外的文件中写了这一行,这并没有解决问题。 logging.FileHandler(... encoding='utf-8') ? 它也没有帮助。 请张贴您的日志字典。 【参考方案1】:

我们解决了这个问题!))

首先,我们编辑文件.../init.d/celeryd。我们在文件中添加了一行:

. /etc/profile.d/lang.sh.

其次,我们在类logging.Formatter(文件.../python2.7/logging/__init__.py)中覆盖了函数format。换句话说,我们创建了一个新类:

class FooFormatter(logging.Formatter):
    def format(self, record):
        if isinstance(record.args, dict):
             for v, k  in records.args.item():
                 records.args[k] = v.decode("utf-8")
        # I do not write everything, but I hope you understand.
        # And there you can do others things.
        return super(FooFormatter, self).format(record)

就是这样!)非常感谢帮助我的策展人。

【讨论】:

以上是关于Celery 无法在“utf-8”中记录字符串错误。 Unicode解码错误的主要内容,如果未能解决你的问题,请参考以下文章

错误:无法加载 celery 应用程序。未找到模块任务

创建第一个 Celery 任务 - Django。错误 - “错误/MainProcess] 消费者:无法连接到 amqp://guest:**@127.0.0.1:5672//:”

在 Celery 中使用 Python 标准日志记录

无法让 Celery 使用 prod 设置处理数字海洋液滴

无法启动 Celery Worker (Kombu.asynchronous.timer)

Celery 无法连接到 RabbitMQ 服务器