在我的代码中,记录器以某种方式打印出事件两次,但传统的print
显示正确的事件数。
select 1,2
select 1,2
2013-04-19 18:37:30,618:4561354752 - SQLLogger - DEBUG - select 1,2
2013-04-19 18:37:30,618:4561354752 - SQLLogger - DEBUG - select 1,2
2013-04-19 18:37:30,618:4565561344 - SQLLogger - DEBUG - select 1,2
2013-04-19 18:37:30,618:4565561344 - SQLLogger - DEBUG - select 1,2
我不清楚为什么在多线程情况下多次发布相同的消息。
import logging
from threading import Thread
class SQLEngine(object):
def __init__(self, DB_PATH):
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s:%(thread)d - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
self.logger = logging.getLogger('SQLLogger')
self.logger.setLevel(logging.DEBUG)
self.logger.addHandler(ch)
def execute(self,SQL,):
self.logger.debug(SQL)
print SQL
class DBWorker(Thread):
def __init__(self, name):
Thread.__init__(self)
self.name = name
def run(self):
db = SQLEngine('')
db.execute('select 1,2')
if __name__ == '__main__':
DBWorker('thread 1').start()
DBWorker('thread 2').start()
答案 0 :(得分:2)
查看logger文档:
记录器永远不会直接实例化,但始终通过模块级函数logging.getLogger(name)实例化。对具有相同名称的getLogger()的多次调用将始终返回对同一Logger对象的引用。
现在你的构造函数正在调用以下代码:
ch = logging.StreamHandler()
self.logger = logging.getLogger('SQLLogger')
self.logger.addHandler(ch)
请注意,不要为每个SQLEngine
对象创建新的记录器,但始终会获得对同一记录器实例的引用。这意味着您总是将处理程序添加到同一个记录器中,因此在创建第二个对象后,您的记录器有两个处理程序,每个处理程序都会打印到屏幕上。
我们只需要注册一个处理程序(例如在SQLEngine
构造函数之外)或在getLogger
中调用__init__
,每个{{1}使用不同的名称实例。
答案 1 :(得分:0)
您已经启动了两个线程,每个线程都有自己的SQLEngine属性对象,在运行相应的线程时会执行该对象。如果您想在多个线程之间共享记录器,那么创建一个可以传递的单个记录器对象将是更好的选择。 GIL将负责其余的工作。
import logging
from threading import Thread
class SQLEngine(object):
def __init__(self, DB_PATH):
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s:%(thread)d - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
self.logger = logging.getLogger('SQLLogger')
self.logger.setLevel(logging.DEBUG)
self.logger.addHandler(ch)
def execute(self,SQL,):
self.logger.debug(SQL)
print (SQL)
class DBWorker(Thread):
def __init__(self, name, logengine):
Thread.__init__(self)
self.name = name
self.logger = logengine
def run(self):
#db = SQLEngine('')
self.logger.execute('select 1,2')
if __name__ == '__main__':
logger = SQLEngine('')
DBWorker('thread 1', logger).start()
DBWorker('thread 2', logger).start()
这只是一个例子。正如@tomasz所提到的,您可以根据您的要求处理此记录器对象