Mat*_*ier 5 python queue logging multiprocessing python-3.x
最近,我面临着在我们的软件中进行多处理的挑战。我想要一个主进程来生成子进程,并且我需要某种方法将日志信息发送回主进程。这主要是因为我们使用的模块将警告和错误消息写入日志对象,并且我们希望这些消息出现在主进程中运行的 GUI 中。
显而易见的方法是编写一个带有 write() 方法的小类,该方法将 put() 放入队列,然后在日志流处理程序中使用此类。然后主进程将从该队列中 get() 将文本发送到 gui。但这似乎不起作用,我不知道为什么
我编写了一些示例代码来演示该问题。它使用日志对象在子进程中写入队列,然后主进程尝试从队列中读取,但失败。有人可以帮我弄清楚这有什么问题吗?
import time, multiprocessing, queue, logging
class FileLikeQueue:
"""A file-like object that writes to a queue"""
def __init__(self, q):
self.q = q
def write(self, t):
self.q.put(t)
def flush(self):
pass
def func(q):
"""This function just writes the time every second for five
seconds and then returns. The time is sent to the queue and
to a logging object"""
stream = FileLikeQueue(q)
log = logging.getLogger()
infohandler = logging.StreamHandler(stream)
infohandler.setLevel(logging.INFO)
infoformatter = logging.Formatter("%(message)s")
infohandler.setFormatter(infoformatter)
log.addHandler(infohandler)
t1 = time.time()
while time.time() - t1 < 5: #run for five seconds
log.info('Logging: ' + str(time.time()))
q.put('Put: %s' % str(time.time()))
time.sleep(1)
def main():
q = multiprocessing.Queue()
p = multiprocessing.Process(target=func, args=(q,))
p.start()
#read the queue until it is empty
while True:
try:
t = q.get()
except queue.Empty:
break
print(t)
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
我期望输出是:
Logging: 1333629221.01
Put: 1333629221.01
Logging: 1333629222.02
Put: 1333629222.02
Logging: 1333629223.02
Put: 1333629223.02
Logging: 1333629224.02
Put: 1333629224.02
Logging: 1333629225.02
Put: 1333629225.02
Run Code Online (Sandbox Code Playgroud)
但我得到的是:
Put: 1333629221.01
Put: 1333629222.02
Put: 1333629223.02
Put: 1333629224.02
Put: 1333629225.02
Run Code Online (Sandbox Code Playgroud)
因此 func() 中的 put() 操作有效,但日志记录无效。为什么?
谢谢。
您的问题在于日志记录模块的配置:
你需要打电话log.setLevel(logging.INFO)
。默认的日志级别是WARNING
,所以你的日志没有任何作用。
您确实调用setLevel
了处理程序对象,但记录的消息永远不会到达处理程序,因为它们已被记录器过滤。无需调用处理setLevel
程序本身,因为它默认处理所有消息。