1

我有一个支持多线程的 HTTP Server 类,在将结果写回客户端时,它也会写入一些日志(Logging 模块)。它减慢了请求,并且由于 POST/GET 方法仅在“返回”发生后返回,所以我必须在发送结果之前写入日志。我希望通过打开另一个接收消息的线程并写入日志来做到这一点。我希望将我的 Logging 对象设置为“静态”,或者是一个唯一的类成员,并且共享给所有可以获得锁定并使用它的线程。

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('info', "some info") 相反,我希望这个调用实际上会打开一个新线程,它拥有对单个 Logging 的引用我在 Logger 类中进行了配置。

4

2 回答 2

3

启动线程也有开销。

所以我建议你编写一个具有三个公共功能的模块;

  • start(filename)启动日志记录线程
  • write(txt)写入日志文件。
  • stop()停止日志记录线程。

write函数将要登录的文本放入 FIFOQueue并返回到调用线程。

日志记录线程从 中读取项目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)

使用日志模块而不是简单地写入文件作为练习留给读者。

于 2013-08-20T17:48:11.810 回答
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,) )
于 2013-08-20T17:43:48.543 回答