Celery 无法在 'utf-8' 中记录字符串错误。 Unicode解码错误
Celery can't log string errors in 'utf-8'. UnicodeDecodeError
有时我需要用俄语的参数创建错误。例如:
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': "курочка"})
我认为 Celery 有问题。如果你打开<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 在我的例外 returns 中只有俄语单词 str 并且全部失败。所以是Celery的问题
我也知道我的LANG=“ru_RU.UTF-8”。我知道:
sys.getdefaultencoding()
returns «ascii»,
如果我写:
reload(sys)
sys.setdefaultencoding(«UTF-8»)
它会解决我的问题,我会收到俄语消息。
但我想有其他解决方案,因为我不同意这个决定。
我们解决了这个问题!))
首先,我们编辑了文件.../init.d/celeryd。我们在文件中添加了行:
. /etc/profile.d/lang.sh
.
其次,我们覆盖了 class logging.Formatter
中的函数 format
(文件 .../python2.7/logging/__init__.py
)。换句话说,我们创建了一个新的 class:
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)
就这些了!)非常感谢帮助我的策展人
有时我需要用俄语的参数创建错误。例如:
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': "курочка"})
我认为 Celery 有问题。如果你打开<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 在我的例外 returns 中只有俄语单词 str 并且全部失败。所以是Celery的问题
我也知道我的LANG=“ru_RU.UTF-8”。我知道:
sys.getdefaultencoding()
returns «ascii»,
如果我写:
reload(sys)
sys.setdefaultencoding(«UTF-8»)
它会解决我的问题,我会收到俄语消息。
但我想有其他解决方案,因为我不同意这个决定。
我们解决了这个问题!))
首先,我们编辑了文件.../init.d/celeryd。我们在文件中添加了行:
. /etc/profile.d/lang.sh
.
其次,我们覆盖了 class logging.Formatter
中的函数 format
(文件 .../python2.7/logging/__init__.py
)。换句话说,我们创建了一个新的 class:
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)
就这些了!)非常感谢帮助我的策展人