2013-08-20 4 views
1

У меня есть класс HTTP Server, поддерживающий многопоточность, что при записи результата клиенту он записывает также некоторые журналы (модуль журнала). Это замедляет запрос, и поскольку методы POST/GET возвращаются только после появления «return», я должен написать журнал, прежде чем отправить результат. Я хочу сделать это, открыв еще один поток, который получит сообщение, и напишет журнал. Я хочу, чтобы мой объект ведения журнала был «статичным» или членом класса, который является одним и единственным, и делится на все потоки, которые могут получить блокировку на нем и использовать его.Многопоточность Python для записи журнала

import logging 

LOG_FILENAME = 'babyServer.log' 
class Logger(object): 
    logging.basicConfig(level=logging.DEBUG, 
        format='%(asctime)s %(levelname)-8s %(message)s', 
        datefmt='%a, %d %b %Y %H:%M:%S', 
        filename='serverLog.log', 
        filemode='wa') 


    @classmethod 
    def Write(cls,level,log): 
     level = level.lower() 
     if level == 'error': 
      logging.error(log) 
     if level == 'info': 
      logging.info(log) 
     if level == 'exception': 
      logging.exception(log) 

Так где-то за пределами этого файла, я в настоящее время вызова, такие как Logger.Write («Информация», «некоторая информация») Вместо этого, я хотел бы, чтобы этот призыв будет фактически открыть новую тему , которому принадлежит ссылка на единственное Logging I, настроенное в классе Logger.

ответ

2

Начиная нить также накладные расходы.

Поэтому я бы предложил вам написать модуль, который имеет три публичные функции;

  • start(filename) начать протоколирования нить
  • write(txt) для записи в лог-файл.
  • stop(), чтобы остановить нишу регистрации.

write функция помещает текст для входа в FIFO Queue и возвращается к вызывающему потоку.

Регистрирующий поток читает элементы из Queue и записывает их в файл журнала.

Скажите, что у вас есть файл log.py;

"""Module to log to a file.""" 

import Queue 
import threading 

_name = None 
_lt = None 
_q = None 
_stop = False 


def _run(): 
    while not _stop: 
     txt = _q.get() 
     with open(_name, 'a+') as logfile: 
      logfile.write(txt) 


def start(name): 
    global _lt, _q, _name 
    if _name: 
     raise RuntimeError('Logging already initialized') 
    _name = name 
    _q = Queue.Queue() 
    _lt = threading.Thread(target=_run) 
    _lt.start() 


def stop(): 
    global _stop 
    _stop = True 
    _lt.join() 


def write(txt): 
    _q.put(txt, block=False) 

Использование модуля регистрации, а не просто обращение к файлу, остается в качестве упражнения для читателя.

+0

Не могли бы вы пояснить (используя мой исходный код) Как поддерживать взаимные переменные из разных потоков с помощью механизма блокировки? Либо в очереди, либо через мьютекс. Я не уверен, как это происходит с общими переменными. – buddy123

+0

Что позволяет избегать создания экземпляра каждый раз, когда возникает новая запись? Мне кажется, что его воссоздают каждый раз снова и снова – buddy123

+0

Нить '_lt' создается и запускается только в функции' start() ', которую можно назвать только _once_. Если вы попытаетесь снова вызвать 'start()', это вызовет исключение.Единственное, что 'write()' делает, помещает что-то в очередь, не более того. –

0

Я нашел очень простое решение, используя модуль резьбы.

import thread 

Затем, когда мне нужно вызвать мою функцию протоколирования, я просто использовать его следующим образом:

thread.start_new_thread(logging.error, (log,)) 

, где в этом примере, logging.error является встроенная функция протоколирования, что делает журнал ошибок и (log) - это кортеж (как требуется интерфейсу) моего сообщения журнала для записи. Это, как я ожидал, существенно повысить производительность

@classmethod 
def Write(cls,level,log): 
    level = level.lower() 
    if level == 'error': 
     thread.start_new_thread(logging.error, (log,)) 
    if level == 'info': 
     thread.start_new_thread(logging.info, (log,)) 
    if level == 'exception': 
     thread.start_new_thread(logging.exception, (log,)) 
Смежные вопросы