Регистрация в рабочих потоках, порожденных из приложения пилонов, похоже, не работает - PullRequest
0 голосов
/ 05 марта 2010

У меня есть приложение pylons, в котором при определенных обстоятельствах я хочу создать несколько рабочих потоков для обработки элементов в очереди.Прямо сейчас мы не используем ThreadPool (было бы идеально, но мы добавим это позже).Основная проблема заключается в том, что ведение журнала рабочих потоков не записывается в файлы журнала.

Когда я запускаю код вне приложения pylons, ведение журнала работает нормально.Поэтому я думаю, что это как-то связано с обработчиком журнала пилонов, но я не уверен, что.

Вот базовый пример кода (обрезанный):

import logging
log = logging.getLogger(__name__)

import sys
from Queue import Queue
from threading import Thread, activeCount

def run(input, worker, args = None, simulteneousWorkerLimit = None):
    queue = Queue()
    threads = []

    if args is not None:
        if len(args) > 0:
            args = list(args)
            args = [worker, queue] + args
            args = tuple(args)
        else:
            args = (worker, queue)

    # start threads
    for i in range(4):
        t = Thread(target = __thread, args = args)
        t.daemon = True
        t.start()
        threads.append(t)

    # add ThreadTermSignal
    inputData = list(input)
    inputData.extend([ThreadTermSignal] * 4)

    # put in the queue
    for data in inputData:
        queue.put(data)

    # block until all contents are downloaded
    queue.join()
    log.critical("** A log line that appears fine **")

    del queue
    for thread in threads:
        del thread
    del threads

class ThreadTermSignal(object):
    pass

def __thread(worker, queue, *args):
    try:
        while True:
            data = queue.get()
            if data is ThreadTermSignal:
                sys.exit()
            try:
                log.critical("** I don't appear when run under pylons **")
            finally:
                queue.task_done()
    except SystemExit:
        queue.task_done()
        pass

Обратите внимание, чтоlog lin в методе RUN будет отображаться в файлах журнала, но строка журнала в рабочем методе (который запускается в порожденном потоке) не отображается.Любая помощь будет оценена.Спасибо

** РЕДАКТИРОВАТЬ: я должен упомянуть, что я пытался передать переменную "log" в рабочий поток, а также переопределить новую переменную "log" в потоке, но ни одна из них не работала.*** РЕДАКТИРОВАТЬ: Добавление конфигурации, используемой для приложения пилонов (который выходит из файла INI).Таким образом, приведенный ниже фрагмент взят из файла INI.

[loggers]
keys = root

[handlers]
keys = wsgierrors

[formatters]
keys = generic

[logger_root]
level = WARNING
handlers = wsgierrors

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

[handler_wsgierrors]
class = pylons.log.WSGIErrorsHandler
args = ()
level = WARNING
format = generic

Ответы [ 2 ]

1 голос
/ 06 марта 2010

Одна вещь, которую следует отметить при ведении журнала, - это то, что если исключение возникает при отправке события журнала (по какой-либо причине), то исключение обычно проглатывается, и ему не разрешается потенциально закрыть приложение только из-за ошибки ведения журнала. (Это зависит от используемых обработчиков и значения logging.raiseExceptions). Итак, есть пара вещей, которые нужно проверить:

  • То, что ваше форматирование сообщений журнала очень простое, возможно, просто с использованием% (message) s, пока не найдете проблему.
  • Убедитесь, что Pylons не отключился и не связался с обработчиками по какой-либо причине. Вы не опубликовали свой код инициализации регистрации, поэтому я не уверен, какие обработчики и т. Д. Вы используете. Вы можете напечатать log.getEffectiveLevel(), чтобы увидеть, было ли подробное ведение журнала выключено (маловероятно для КРИТИЧЕСКОГО, но вы никогда не узнаете).

Если вы добавите операторы печати вместе с вашими лог-отчетами, будут ли они выводить данные так, как вы ожидаете?

Обновление: Мне известно об ограничении для mod_wsgi и печати, но это относится только к sys.stdout. Вы можете, например,

print >> sys.stderr, some_data

или

print >> open('/tmp/somefile', 'a'), some_data

без проблем.

Также: вы должны знать, что вызов logging.config.fileConfig() (который, предположительно, реализует описанную вами конфигурацию) отключает любые существующие регистраторы, если они не имеют явного имени или не являются потомками регистраторов, явно названных в , файл конфигурации. Хотя это может показаться странным, это потому, что конфигурация предназначена для замены любой существующей конфигурации, а не для ее расширения; и поскольку потоки могут указывать на существующие средства ведения журнала, они отключены, а не удалены. Вы можете проверить атрибут disabled регистратора, чтобы узнать, отключил ли регистратор fileConfig() - что может быть вашей проблемой.

0 голосов
/ 05 марта 2010

Вы можете попытаться передать переменную log потоку через аргументы ( args ).

...