Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中实现来自多个线程的自定义输出日志记录_Python_Multithreading_Logging - Fatal编程技术网

在python中实现来自多个线程的自定义输出日志记录

在python中实现来自多个线程的自定义输出日志记录,python,multithreading,logging,Python,Multithreading,Logging,我在Python多线程方面的实践相当糟糕。现在,我正在研究如何从多个线程获取日志信息。我看到了很多不同的方法,但我想从简单的方法开始。因此,任务是创建几个线程,并从每个线程记录数据。为了识别日志的来源,我想在日志输出中添加一些自定义标记。我知道日志库有一个reach LogRecord属性thread、threadName等,它工作得很好。所以,我有一些例子,并做了一些修改。以下是完整的代码: 导入日志记录 导入线程 导入时间 logger=logging.getLogger syslog=lo

我在Python多线程方面的实践相当糟糕。现在,我正在研究如何从多个线程获取日志信息。我看到了很多不同的方法,但我想从简单的方法开始。因此,任务是创建几个线程,并从每个线程记录数据。为了识别日志的来源,我想在日志输出中添加一些自定义标记。我知道日志库有一个reach LogRecord属性thread、threadName等,它工作得很好。所以,我有一些例子,并做了一些修改。以下是完整的代码:

导入日志记录 导入线程 导入时间 logger=logging.getLogger syslog=logging.StreamHandler 格式化程序=日志记录。格式化程序“%projects:%threadx” “%levelname-8s” “%messages” syslog.setFormatterformatter logger.setLevellogging.DEBUG logger.addHandlersyslog 类ContextFilterlogging.Filter: 定义初始自我,项目: superContextFilter,self.\u init__ self.project=project def过滤器自身,记录: record.project=self.project 返回真值 def workerargs: 而不是args['stop']: logging.debug'Hi from{}.formatargs['project'] 时间是0.5 def主: projects=['project_1','project_2'] 信息={'stop':False} 线程=[] 对于项目中的项目: 信息['project']=项目 logger.addFilterContextFilterproject thread=threading.Threadtarget=worker,args=info, thread.start threads.appendthread 尽管如此: 尝试: logging.debug'Hello from main' 时间1.75 除键盘中断外: 信息['stop']=True 打破 对于螺纹中的t: t、 加入 如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu': 主要的 以下是输出结果:

project_2 : 7fa627e77700 DEBUG    Hi from project_2
project_2 : 7fa6293d0700 DEBUG    Hello from main
project_2 : 7fa627676700 DEBUG    Hi from project_2
project_2 : 7fa627e77700 DEBUG    Hi from project_2
project_2 : 7fa627676700 DEBUG    Hi from project_2
project_2 : 7fa627e77700 DEBUG    Hi from project_2
project_2 : 7fa627676700 DEBUG    Hi from project_2
project_2 : 7fa627e77700 DEBUG    Hi from project_2
project_2 : 7fa627676700 DEBUG    Hi from project_2
project_2 : 7fa6293d0700 DEBUG    Hello from main
project_2 : 7fa627e77700 DEBUG    Hi from project_2

事实上,这不是我所期望的。你能告诉我我做错了什么吗?

你到底期望什么?如果您想知道为什么Hi from不显示项目名称,请尝试:

logging.debug('Hi from {}'.format(args['project']))
编辑:为了回答您的评论,事实上您确实从两个线程获得了日志。 但是您的infoobject是共享的。传递args=info时,实际上传递的是对info对象的引用,而不是副本

因此,第一次执行for循环时,会得到info['project']=project_1,但第二次执行时,info['project']会被project_2覆盖


您的工作线程只是从相同的信息目录中读取值。

部分问题来自对象变量的传递。当您传递args=info时,您传递的是稍后修改并传递给下一个对象的对象,而不是该对象的副本。将同一个对象传递给多个线程可能会变得危险,这可能导致

首先,我们可以删除ContextFilter。我们将它们添加到全局记录器中,而不是跟踪每个线程的任何内容

import logging
import threading
import time

logger = logging.getLogger()
syslog = logging.StreamHandler()
formatter = logging.Formatter('%(project)s : %(thread)x '
                              '%(levelname)-8s '
                              '%(message)s')
syslog.setFormatter(formatter)
logger.setLevel(logging.DEBUG)
logger.addHandler(syslog)
我发现在一般情况下构建threading.Thread类对于除最简单任务外的所有任务都更有用

此类维护自己的运行状态,并使用正确的额外数据构建自己的日志适配器

现在我们需要改变一些事情。我们需要使用我们自己的工人阶级

我们不需要对logger做任何事情,类将管理自己的LoggerAdapter

我们希望确保每次都创建一个新的info对象,这非常简单,我们可以直接在函数调用{'project':project}中传递它,而无需指定变量

我们需要确保在从主线程进行日志记录时传递项目变量。用另一个LoggerAdapter可能更好

一旦我们中断了循环,我们可以要求每个线程停止,然后等待每个线程的连接可能会被移动到Worker类的stop方法中

此代码生成如下结果:

project_1 : 7f4b44180700 DEBUG    Hi from project_1
project_2 : 7f4b4397f700 DEBUG    Hi from project_2
main : 7f4b45c8d700 DEBUG    Hello from main
project_1 : 7f4b44180700 DEBUG    Hi from project_1
project_2 : 7f4b4397f700 DEBUG    Hi from project_2
project_1 : 7f4b44180700 DEBUG    Hi from project_1
project_2 : 7f4b4397f700 DEBUG    Hi from project_2
project_1 : 7f4b44180700 DEBUG    Hi from project_1
project_2 : 7f4b4397f700 DEBUG    Hi from project_2
main : 7f4b45c8d700 DEBUG    Hello from main
project_1 : 7f4b44180700 DEBUG    Hi from project_1

有许多方法可以整理代码并使其更具可读性,但这至少应该为您提供一些学习和开始实验的起点。当您了解有关线程的更多信息时,您还应该阅读有关机制的内容。我最近开始在线程之间进行通信,导致代码更易于调试。

谢谢,我错过了括号,我的疏忽。问题是我希望看到来自不同线程的日志,而不仅仅是来自“project_2”和Main。请记住接受其中一个答案
def main():
    projects = ['project_1', 'project_2']
    threads = []
    for project in projects:
        thread = Worker({'project': project})
        thread.start()
        threads.append(thread)
    while True:
        try:
            logging.debug('Hello from main', extra={'project':'main'})
            time.sleep(1.75)
        except KeyboardInterrupt:
            break
    for t in threads:
        t.stop()
    for t in threads:
        t.join()

if __name__ == '__main__':
    main()
project_1 : 7f4b44180700 DEBUG    Hi from project_1
project_2 : 7f4b4397f700 DEBUG    Hi from project_2
main : 7f4b45c8d700 DEBUG    Hello from main
project_1 : 7f4b44180700 DEBUG    Hi from project_1
project_2 : 7f4b4397f700 DEBUG    Hi from project_2
project_1 : 7f4b44180700 DEBUG    Hi from project_1
project_2 : 7f4b4397f700 DEBUG    Hi from project_2
project_1 : 7f4b44180700 DEBUG    Hi from project_1
project_2 : 7f4b4397f700 DEBUG    Hi from project_2
main : 7f4b45c8d700 DEBUG    Hello from main
project_1 : 7f4b44180700 DEBUG    Hi from project_1