2015-05-07 2 views
0

Я использую Celery 3.1.18 с Python 2.7.8 на CentOS 6.5.Журнал работника сельдерея содержит вопросительные знаки (???) вместо правильных символов юникода

В модуле сельдерея задачи, у меня есть следующий код:

# someapp/tasks.py 
from celery import shared_task 
from celery.utils.log import get_task_logger 

logger = get_task_logger(__name__) 


@shared_task() 
def foo(): 
    logger.info('Test output: %s', u"测试中") 

я использую the initd script here запустить сельдерей работник. Кроме того, я поставил следующие параметры в /etc/default/celeryd:

CELERYD_NODES="bar" 

# %N will be replaced with the first part of the nodename. 
CELERYD_LOG_FILE="/var/log/celery/%N.log" 

# Workers should run as an unprivileged user. 
# You need to create this user manually (or you can choose 
# a user/group combination that already exists, e.g. nobody). 
CELERYD_USER="nobody" 
CELERYD_GROUP="nobody" 

Так что мой файл журнала находится в /var/log/celery/bar.log.

Однако после того, как задача выполняется работником, выше файл журнала показывает:

[2015-05-07 03:51:14,438: INFO/Worker-1/someapp.tasks.foo(...)] Test output: ??? 

ЮНИКОДу символы исчезли, сменившись ряд вопросительных знаков.

Как я могу вернуть символы Unicode в файле журнала?

+0

Вы уверены, что эта проблема связана с сельдереем? Что произойдет, если вы сделаете то же самое на регулярном скрипте python? Также, что произойдет, если вы укажете 'u" 测试 中 ".encode ('utf-8')' вместо просто 'u" 测试 中 "?? – Dacav

+0

В обычном скрипте Python запись в Юникоде прекрасна. Кроме того, если я укажу '' 'u" 测试 中 ".encode ('utf-8')' '' вместо '' 'u" 测试 中 "' '' в моем примере, журнал Celery показывает '' 'UnicodeDecodeError : 'ascii' codec не может декодировать байт ... '' '. – Rockallite

ответ

5

Вам необходимо установить LANG=zh_CN.UTF-8 в среде, в которой вы запускаете приложение для сельдерея.

Если вы используете celeryd, есть простой способ, установить CELERY_BIN="env LANG=zh_CN.UTF-8 /path/to/celery/binary в /etc/default/celeryd

Пояснение:

  1. сельдерея использует ColorFormatter для сообщения форматирования, которое определено в celery.utils.log.
  2. ColorFormatter конвертирует unicode в str с kombu.utils.encoding.safe_str.
  3. kombu.utils.encoding.safe_str кодирует юникод к Силе с кодировкой возвращается от default_encoding, определенного в kombu.utils.encoding
  4. default_encoding возвращается getattr(get_default_encoding_file(), 'encoding', None) or sys.getfilesystemencoding()
  5. Кроме того, я не нашел сельдерей набор кодирования в явном виде, так что я думал, сельдерей использую sys.getfilesystemencoding() как кодирование для преобразования Юникода ул.
  6. sys.getfilesystemencoding's manual говорит, что:

    On Unix, the encoding is the user’s preference according to the result of nl_langinfo(CODESET), or None if the nl_langinfo(CODESET) failed

  7. So, setting LANG=zh_CN.UTF8 in the celery process environment tells celery to convert unicode to str by UTF8.

+0

Спасибо. Это действительно решает мою проблему. Мне все еще интересно, как это работает. – Rockallite

+0

@ Rockallite Пояснение добавлено. – WKPlus

+0

Очень подробный ответ! Я пытаюсь запустить '' 'LANG = python -c 'import sys; print sys.getfilesystemencoding() '' '' на CentOS, и он говорит '' 'ANSI_X3.4-1968'''. Без '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'LANG = en_US.UTF-8''' в оболочке bash). '' 'kombu''' кодирует unicode на str с аргументом' '' error = 'replace'''', поэтому все, что выходит за пределы ANSI, становится вопросительными знаками. – Rockallite

Смежные вопросы