python的多进程、logging模

一、多进程multiprocessing

1、Process类

  • Process类遵循了Thread类的API,减少了学习的难度
举例 :单线程、多线程和多进程的比较

    import multiprocessing
    import datetime

    #计算
    def calc(i):
        sum = 0
        for _ in range(1000000):
            sum += 1

        print(i, sum)

    if __name__ == "__main__": start = datetime.datetime.now() ps = [] for i in range(5): #多进程 p = multiprocessing.Process(target=calc, args=(i,), name="cal-{}".format(i)) ps.append(p) p.start() for p in ps: p.join() delta = (datetime.datetime.now() - start).total_seconds() print(delta) print('===end===') 单线程,多线程都跑了4分钟,而多进程用了1分钟,这是真并行 

2、进程间同步

  • 进程间同步提供了和线程同步一样的类,使用的方法一样,使用的效果也类似,不过,进程间代价要高于线程,而且底层实现是不同的,只不过python屏蔽了这些,让用户简单使用
  • multiprocessing还提供共享内存,服务器进程来共享数据,还提供了Queue队列,Pipe管道用于进程间通信

3、通信方式不同

  • 多进程就是启动多个解释器进程,进程间通信必须序列化,反序列化
  • 数据的线程安全性问题

4、进程池的举例

进程池的举例
    
import multiprocessing
import datetime

#计算
def calc(i):
    sum = 0
    for _ in range(1000000):
        sum += 1
    print(i, sum)

if __name__ == "__main__": start = datetime.datetime.now() p = multiprocessing.Pool(5) for i in range(5): p.apply_async(calc, args=(i,)) p.close() p.join() delta = (datetime.datetime.now() - start).total_seconds() print(delta) print('end============')

5、多进程,多线程的选择

  • CPU密集型:CPython中使用到了GIL,多线程的时候锁互相竞争,且多核优势不能发货,Python多进行效率更高
  • IO密集型:合适是用多线程,减少IO序列化开销,且在IO等待的时候,切换到其他线程继续执行,效率不错

 

二、logging模块

  •  日志级别 数值
  •  CRITICAL  50
  •  ERROR     40
  •  WARNING   30,默认级别
  •  INFO      20
  •  DEBUG     10
  •  NOTSET    0
  • 日志级别指的是生产日志的事件的严重程度,设置一个级别后,严重程度低于设置值的日志消息将被忽略

1、格式字符串

  • 1、日志消息内容 %(message)s :当调用Formatter.format()时设置
  • 2、asctime      %(asctime)s : 创建LogRecord时的可读时间,默认情况下,它的格式为时间
  • 3、函数名       %(funcName)s :日志调用所在的函数名
  • 4、日志级别名称 %(levelname)s : 消息的级别名称'DEBUG','INFO','WARNING','ERROR','CRITICAL'
  • 5、模块         %(module)s    : 模块名
  • 6、进程ID       %(process)d   :  进程ID
  • 7、进程名称     %(processName)s : 进程名
  • 8、线程ID       %(thread)d    : 线程ID
  • 9、线程名称     %(threadName)s : 线程名字

2、默认级别 举例

    import logging

    FORMAT  = '%(asctime)-15s\tThread  info: %(thread)d %(threadName)s %(message)s'
    logging.basicConfig(format=FORMAT)

    logging.info('I am {}'.format(20))   #info不显示 logging.warning('I am {}'.format(20)) #warning默认级别

3、构建消息

import logging

    FORMAT  = '%(asctime)-15s\tThread  info: %(thread)d %(threadName)s %(message)s'
    logging.basicConfig(format=FORMAT,level=logging.INFO)


    logging.info('I am {}'.format(20))   #单一字符串 logging.warning('I am %d %s', 20, 'years old') #c风格 上例是基本的使用方法,大多数时候,使用的是info,正常运行信息的输出

4、日志级别和格式字符串扩展的例子

import logging

    FORMAT  = '%(asctime)-15s\tThread info: %(thread)d %(threadName)s %(message)s %(school)s'
    logging.basicConfig(format=FORMAT,level=logging.WARNING)

    d = {'school': 'magedu.com'} logging.info('I am %s %s', 20, 'years old', extra=d) logging.warning('I am %s %s', 20, 'years old', extra=d) #c风格

5、输出到文件

    import logging
    logging.basicConfig(format='%(asctime)s %(message)s', filename='c:/test')
    for _ in range(5): logging.warning('this event was logged')

6、Logger类

  •  使用工厂方法返回一个Logger类:logging.getLogger([name=None])
  •  指定name,返回一个名称为name的Logger实例,如果再次使用相同的名字,是实例化一个对象
  •  未指定name,返回Logger实例,名称是root,即根Logger
  •  Logger是层次结构的,使用.点号分割,如'a','a.b'或’a,b,c,d',a是a.b的父parent

7、总结

  • 每一个Logger实例的level如同入口,让水流进来,如果这个门槛太高,信息就进不来;例如log3.warning('log3),如果log3定义的级别高,就不会有信息通过log3
  • 如果level没有设置,就用父logger,如果父logger的level没有设置,继续找父的父的,最终可以找到root上,如果root设置了就他的,如果没有设置,root的默认值是WARNINF
  • 消息传递流程:
  •   在某个logger上产生某种级别的消息,首先和logger的level检查,如果消息level低于logger
  •   的EffectiveLevel有效级别,消息丢弃,如果通过检查后,消息交给交给logger所有的handler处理,
  •   每一个handler需要和自己的level比较来决定是否处理

 

转载于:https://www.cnblogs.com/jiangzuofenghua/p/11451300.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python中,可以使用`multiprocessing`块创建多个进程来并行执行任务。当多个进程同时执行时,由于每个进程都有自己的执行环境,因此它们的日志信息需要分别记录。为了实现多进程的日志记录,可以使用`multiprocessing`块的`Queue`来处理日志信息的传递。 首先,我们可以在主进程中创建一个`Queue`对象,用于接收各个子进程的日志信息。然后,将这个`Queue`对象作为参数传递给每个子进程,在子进程中通过`logging`块将日志信息发送到这个`Queue`中。主进程可以通过不断从`Queue`中获取日志信息并进行记录。 具体实现代码如下: ```python import logging import multiprocessing from multiprocessing import Queue # 配置logging logging.basicConfig(level=logging.INFO, format='%(asctime)s %(processName)s %(message)s') # 获取日志队列 def get_logger(queue): # 配置logger logger = logging.getLogger() logger.setLevel(logging.INFO) # 设置Handler handler = logging.QueueHandler(queue) logger.addHandler(handler) # 日志输出到控制台 console = logging.StreamHandler() console.setLevel(logging.INFO) logger.addHandler(console) logger.info('sub process started.') if __name__ == '__main__': # 创建日志队列 queue = Queue() # 创建子进程 p = multiprocessing.Process(target=get_logger, args=(queue,)) p.start() # 创建主进程的logger logger = logging.getLogger() logger.setLevel(logging.INFO) handler = logging.StreamHandler() handler.setLevel(logging.INFO) logger.addHandler(handler) # 主进程等待并获取日志信息进行记录 while True: try: record = queue.get(timeout=1) logger.handle(record) except Exception as e: break logger.info('all sub processes finished.') ``` 通过这种方式,可以实现多个子进程并行执行任务,并且可以记录每个子进程的日志信息,方便日志的统一管理和分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值