logging模块

1.logger的高级

相关组件

一个记录器可以绑定多个处理器

名称 作用
Loggers 记录器,提供应用程序代码直接使用的接口
Handlers 处理器,将记录器产生的日志发送至目的地
Filters 过滤器,提供更好的粒度控制,决定哪些日志会被输出
Formatters 格式化器,设置日志内容的组成结构和消息字段

logging的日志等级

默认的日志级别为WARNING

日志等级(level) 描述
DEBUG 最详细的日志信息,典型应用场景是 问题诊断
INFO 信息详细程度仅次于DEBUG,通常只记录关键节点信息,用于确认一切都是按照我们预期的那样进行工作
WARNING 当某些不期望的事情发生时记录的信息(如,磁盘可用空间较低),但是此时应用程序还是正常运行的
ERROR 由于一个更严重的问题导致某些功能不能正常运行时记录的信息
CRITICAL 当发生严重错误,导致应用程序不能继续运行时记录的信息

Handlers

它们将日志分发到不同的目的地。可以是文件、标准输出、邮件、或者通过 socke、htt等协议发送到任何地方
setFormatter():设置当前Handler对象使用的消息格式

  • Streamhandler
    标准输出stout分发器
sh = logging.StreamHandler(stream=None)
  • Filehandler
    将日志保存到磁盘文件的处理器
fh = logging.FileHandler(filename,mode='a',encoding=None,delay=False)
  • BaseRotatingHandler
  • RotatingFilehandler
    滚动的多日志输出,按照时间or其他方式去生成多个日志
  • TimedRotatingfilehandler

以下的使用较少

  • Sockethandler
  • Dataaramhandler
  • Smtphandler
  • Sysloghandler
  • Nteventloghandler
  • Httphandler
  • WatchedFilehandler
  • Qutelehandler
  • Nullhandler

Formatters格式化

%(levelname)-8s:左对齐(不足8位字符,空格占位) %(levelname)8s:右对齐

属性 格式 描述
asctime %(asctime)s 日志产生的时间,默认格式为msecs2003-07-0816:49:45,896
msecs %(msecs)d 日志生成时间的亳秒部分
created %(created)f time.tme)生成的日志创建时间戳
message %(message)s 具体的日志信息
filename %(filename)s 生成日志的程序名
name %(name)s 日志调用者
funcname %( funcname)s 调用日志的函数名
levelname %(levelname)s 日志级別( DEBUG,INFO, WARNING, 'ERRORCRITICAL)
levene %( leveling)s 日志级别对应的数值
lineno %(lineno)d 日志所针对的代码行号(如果可用的话)
module %( module)s 生成日志的模块名
pathname %( pathname)s 生成日志的文件的完整路径
process %(process)d 生成日志的进程D(如果可用)
processname %(processname)s 进程名(如果可用)
thread %(thread)d 生成日志的线程D(如果可用)
threadname %( threadname)s 线程名(如果可用)

2.初步使用

记录器的设置日志输出级别为第一道过滤,然后再是处理器过滤

test.py

import logging
import logging.handlers

# 1.创建一个记录器
mylogger = logging.getLogger('test.demo')
#	日志输出级别,需要比handler低(推荐使用DEBUG级别)
mylogger.setLevel(logging.DEBUG)


# 2.创建处理器handler
# 屏幕输出
simpleHandler = logging.StreamHandler()
simpleHandler.setLevel(logging.DEBUG)	# 屏幕输出级别过滤
# 和文件一样
fileHandler = logging.FileHandler(filename='testDemo.log', mode='a', encoding='utf-8')
fileHandler.setLevel(logging.INFO)	  # 文件输出级别过滤
# soket发送 (SocketHandler在logging.handlers中)
socketHandler = logging.handlers.SocketHandler('127.0.0.1', 9020)
socketHandler.setLevel(logging.WARN)


# 3.formatter格式
# 数字表示:实现了占位对齐
# datefmt可以设置日期格式
simple_format = logging.Formatter("%(asctime)-20s %(levelname)-8s %(filename)-5s:%(lineno)-5d %(message)s")
file_format = logging.Formatter(
  fmt="[%(asctime)-20s] [%(levelname)-5s] [%(threadName)-5s %(thread)-10d] [%(filename)-2s:%(lineno)-2d] %(message)s",
  datefmt="%Y-%m-%d %H:%M:%S"
)
socket_format = logging.Formatter('%(asctime)-20s %(levelname)-8s %(filename)-5s:%(lineno)-5d %(message)s')


# 4.给【处理器】添加【formatter格式】
simpleHandler.setFormatter(simple_format)
fileHandler.setFormatter(file_format)
socketHandler.setFormatter(socket_format)
mylogger.addHandler(socketHandler)


# 5.【记录器】绑定【处理器】
mylogger.addHandler(simpleHandler)
mylogger.addHandler(fileHandler)


# 6.定义一个过滤器(过滤器主要过滤的是logger对象加)
# 表示只输出到 logging.getLogger('test.XXX') test.开头的对象中,其他一概不输出
# flt = logging.Filter("test")
# 关联过滤器
# mylogger.addFilter(flt)	# 可以给logger对象加
# fileHandler.addFilter(flt)	# 也可以给Handler加


# 7.打印日志的代码
name = 'test'
age = 11
mylogger.debug("姓名 %s, 年龄%d", name, age)
mylogger.info("姓名 %s, 年龄%d" % (name, age))
mylogger.debug("姓名 {}, 年龄{}".format(name, age))
mylogger.error(f"姓名{name}, 年龄{age}")
mylogger.warning(f"姓名{name}, 年龄{age}")
mylogger.critical(f"姓名{name}, 年龄{age}")
2022-06-18 17:46:59,577 DEBUG    aa.py:56    姓名 test, 年龄11
2022-06-18 17:46:59,577 INFO     aa.py:57    姓名 test, 年龄11
2022-06-18 17:46:59,577 DEBUG    aa.py:58    姓名 test, 年龄11
2022-06-18 17:46:59,577 ERROR    aa.py:59    姓名test, 年龄11
2022-06-18 17:46:59,587 WARNING  aa.py:60    姓名test, 年龄11
2022-06-18 17:46:59,587 CRITICAL aa.py:61    姓名test, 年龄11

3.错误信息打印

使用exception(e)打印

import logging
import logging.handlers

# 1.创建一个记录器
mylogger = logging.getLogger('test.demo')
#	日志输出级别,需要比handler低(推荐使用DEBUG级别)
mylogger.setLevel(logging.DEBUG)


# 2.创建处理器handler
# 屏幕输出
simpleHandler = logging.StreamHandler()
simpleHandler.setLevel(logging.DEBUG)	# 屏幕输出级别过滤
# 和文件一样
fileHandler = logging.FileHandler(filename='testDemo.log', mode='a', encoding='utf-8')
fileHandler.setLevel(logging.INFO)	  # 文件输出级别过滤
# soket发送 (SocketHandler在logging.handlers中)
socketHandler = logging.handlers.SocketHandler('127.0.0.1', 9020)
socketHandler.setLevel(logging.WARN)


# 3.formatter格式
# 数字表示:实现了占位对齐
# datefmt可以设置日期格式
simple_format = logging.Formatter("%(asctime)-20s %(levelname)-8s %(filename)-5s:%(lineno)-5d %(message)s")
file_format = logging.Formatter(
  fmt="[%(asctime)-20s] [%(levelname)-5s] [%(threadName)-5s %(thread)-10d] [%(filename)-2s:%(lineno)-2d] %(message)s",
  datefmt="%Y-%m-%d %H:%M:%S"
)
socket_format = logging.Formatter('%(asctime)-20s %(levelname)-8s %(filename)-5s:%(lineno)-5d %(message)s')


# 4.给【处理器】添加【formatter格式】
simpleHandler.setFormatter(simple_format)
fileHandler.setFormatter(file_format)
socketHandler.setFormatter(socket_format)
mylogger.addHandler(socketHandler)


# 5.【记录器】绑定【处理器】
mylogger.addHandler(simpleHandler)
mylogger.addHandler(fileHandler)

try:
    int(name)
except Exception as e:
    mylogger.error(e)
    mylogger.exception(e)	# 推荐使用exception打印错误信息

日志信息

# mylogger.error(e)打印的
[2022-06-18 16:33:16 ] [ERROR] [MainThread 8672656896] [y.py:52] invalid literal for int() with base 10: 'test'
# mylogger.exception(e)打印的
[2022-06-18 16:33:16 ] [ERROR] [MainThread 8596639232] [y.py:52] invalid literal for int() with base 10: 'test'
Traceback (most recent call last):
  File "/Users/lxd670/test_pg3/testlog/y.py", line 50, in <module>
    int(name)

4.配置文件配置logging

logging.conf

#记录器:提供应用程序代码直接使用的接口
#设置记录器名称,root必须存在!!!
[loggers]
keys=root,applog

#处理器,将记录器产生的日志发送至目的地
#设置处理器类型
[handlers]
keys=fileHandler,consoleHandler

#格式化器,设置日志内容的组成结构和消息字段
#设置格式化器的种类
[formatters]
keys=simpleFormatter

#设置记录器root的级别与种类
[logger_root]
level=DEBUG
handlers=consoleHandler

#设置记录器applog的级别与种类
[logger_applog]
level=DEBUG 
handlers=fileHandler,consoleHandler
#起个对外的名字
qualname=applog
#继承关系
propagate=0

#设置
[handler_consoleHandler]
class=StreamHandler
args=(sys.stdout,)
level=DEBUG
formatter=simpleFormatter

[handler_fileHandler]
class=handlers.TimedRotatingFileHandler
#在午夜1点(3600s)开启下一个log文件,第四个参数0表示保留历史文件
args=('applog.log','midnight',3600,0)
level=DEBUG
formatter=simpleFormatter

[formatter_simpleFormatter]
format=%(asctime)s|%(levelname)8s|%(filename)s[:%(lineno)d]|%(message)s
#设置时间输出格式
datefmt=%Y-%m-%d %H:%M:%S

文件使用使用

import logging
import logging.config

logging.config.fileConfig('logging.conf')
#使用字典就能从任意格式文件进行配置,字典是一种接口格式
# logging.config.dictConfig({"loggers":"root,applog"})

rootLogger = logging.getLogger('applog')
rootLogger.debug("This is root Logger, debug")

logger = logging.getLogger('cn.cccb.applog')
logger.debug("This is applog, debug")

try:
    int(a)
except Exception as e:
    logger.exception(e)

5.字典配置

文件结构

mylog
  ├── conf.py
  ├── logs
  │   └── demo_2022-06-18.log
  ├── my_handler.py
  └── use_log.py

配置文件-conf.py

'class': 'test.my.TimeHandler'conf.py不需要引入,会自己查

使用的时候需要把当前文件夹添加带环境变量里

import os

# 1.配置日志输出文件加
logfile_dir='./logs'
if not os.path.isdir(logfile_dir):
    os.makedirs(logfile_dir)

    
# 2.配置format(不写字典里,写在外面清晰)
standard_format = '[%(asctime)-20s] [%(levelname)-5s] [%(threadName)-5s %(thread)-10d] [%(filename)-2s:%(lineno)-2d] %(message)s'
simple_format = '%(asctime)-20s %(levelname)-8s %(filename)-5s:%(lineno)-5d %(message)s'


# 3.log配置字典
LOGGING_DIC = {	
    'version': 1,								# 日志的版本号
    'disable_existing_loggers': False,				# 是否继承原有日志
    'formatters': {		# 1.格式化器<<<<<<
        'standard': {
            'format': standard_format
        },
        'simple': {
            'format': simple_format,
            'datefmt':"%Y-%m-%d %H:%M:%S"		# 设置日期格式
        },
    },
    'filters': {},		# 2.过滤器<<<<<<
    'handlers': {		# 3.处理器<<<<<<
        'console': {	# 相当于console=logging.StreamHandler()绑定日志级别、日志格式化
            'level': 'DEBUG',						# 定义级别	
            'class': 'logging.StreamHandler',	                # 绑定Handler
            'formatter': 'simple'						# 绑定formatter
        },
        'default': {
            'level': 'DEBUG',
          	# 绑定自定义TimeHandler(继承WatchedFileHandler)
            'class': 'mylog.my_handler.TimeHandler',
            'formatter': 'standard',					# 绑定formatter	
            'name': 'demo',						# 设置输出日志的文件名
            'file_path': logfile_dir,					# 输出路径
            'when': 'D',							# 按天生成日志
            'backupCount': 14,						# 保留前14天的日志
            'delay': True,							# 
            'encoding': 'utf-8',                                          # 编码
        }
    },
    'loggers': {			# 4.记录器<<<<<<
        'generate': {						       # 相当于 logger = logging.getLogger('generate')
            'handlers': ['default', 'console'],
            'level': 'DEBUG',                                             # 记录器的日志级别输出
            'propagate': True,	# 
        },
        'test.demo': {	                                              # 相当于 logger = logging.getLogger('test.demo')
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

自定义Handler-my_handler.py

文件名_年-月-日-时-分—秒.log

import os
import datetime
from logging.handlers import WatchedFileHandler


class TimeHandler(WatchedFileHandler):
    def __init__(self, name, file_path, backupCount=3, mode='a', when='D', encoding=None, delay=False):
        if not os.path.exists(file_path):
            os.makedirs(file_path)
        self._file_name = name
        self.file_path = file_path
        self.backupCount = backupCount if backupCount > 3 else 3
        self.when = when.upper()
        self.when_dict = {
            'S': "%Y-%m-%d-%H-%M-%S",
            'M': "%Y-%m-%d-%H-%M",
            'H': "%Y-%m-%d-%H",
            'D': "%Y-%m-%d"
        }
        self.file_name = "{}_{}.log".format(self._file_name, datetime.datetime.now().strftime(self.when_dict.get(self.when,'D')))
        filename = os.path.join(self.file_path, self.file_name)
        super().__init__(filename=filename, mode=mode,encoding=encoding, delay=delay)

    def doChangeFile(self):
        if self.stream:
            self.stream.close()
            self.stream = None
        if not self.delay:
            self.stream = self._open()
        if self.backupCount > 0:
            for s in self.getFilesToDelete():
                print(f'remove :{s}')
                os.remove(s)

    def getFilesToDelete(self):
        fileNames = os.listdir(self.file_path)
        result = []
        for fileName in fileNames:
            if fileName.startswith(f"{self._file_name}_{datetime.datetime.now().strftime(self.when_dict.get(self.when,'D'))}"):
                result.append(os.path.join(self.file_path, fileName))
        result.sort()
        if len(result) <= self.backupCount:
            result = []
        else:
            result = result[:len(result) - self.backupCount]
        return result

    def emit(self, record):
        current_file_name = "{}_{}.log".format(self._file_name,datetime.datetime.now().strftime(self.when_dict.get(self.when,'D')))
        if current_file_name != self.file_name:
            self.doChangeFile()
            self.file_name = current_file_name
            self.baseFilename = os.path.abspath(os.path.join(self.file_path, self.file_name))
            if self.stream:
                self.stream.flush()
                self.stream.close()
            self.stream = self._open()
            self._statstream()
        self.reopenIfNeeded()
        super().emit(record)

使用-use_log.py

可以在定义在mylog里面,也可定义在外面

import logging.config
# 导入配置文件
from mylog.conf import LOGGING_DIC
logging.config.dictConfig(LOGGING_DIC)
# 获取日志对象
generate_logger = logging.getLogger('generate')
test_demo_logger = logging.getLogger('test.demo')
# 使用
generate_logger.info("generate test")
test_demo_logger.info("test.demo test")
# 控制台输出
2022-06-18 17:42:58  INFO     use_log.py:9     generate test
2022-06-18 17:42:58  INFO     use_log.py:10    test.demo test
# 日志文件
[2022-06-18 17:42:58,979] [INFO ] [MainThread 8606850560] [use_log.py:9 ] generate test

5.socket解决多进程日志问题

流程

客户端 -> socket -> 服务端
客户端发送的是一个字典,里面包含了日志信息(网络传输是byte类型,所以需要序列化)
服务端获取日志字典中的name创建logger对象(单例模式)
然后把其他信息交给logger对象处理

打印 obj = self.unPickle(chunk)
{'name': 'test.demo', 'msg': '姓名test, 年龄11', 'args': None, 'levelname': 'ERROR', 'levelno': 40, 'pathname': '/Users/lxd670/test_pg3/testlog/y.py', 'filename': 'y.py', 'module': 'y', 'exc_info': None, 'exc_text': None, 'stack_info': None, 'lineno': 46, 'funcName': '<module>', 'created': 1655548199.731752, 'msecs': 731.7519187927246, 'relativeCreated': 12.069940567016602, 'thread': 8627547648, 'threadName': 'MainThread', 'processName': 'MainProcess', 'process': 56709, 'asctime': '2022-06-18 18:29:59'}

文件路径

ser_log
  ├── conf.py
  ├── logs
  │   └── socket_2022-06-18.log
  ├── my_handler.py
  └── run.py
client.py

服务端

服务端不是特殊情况只需配置一个日志轮询handler就好了

使用RotatingFilehandlerTimedRotatingfilehandler

配置文件 - conf.py
import os

logfile_dir = './logs'
if not os.path.isdir(logfile_dir):
    os.makedirs(logfile_dir)

standard_format = '[%(asctime)-20s] [%(levelname)-5s] [%(threadName)-5s %(thread)-10d] [%(filename)-2s:%(lineno)-2d] %(message)s'
simple_format = '%(asctime)-20s %(levelname)-8s %(filename)-5s:%(lineno)-5d %(message)s'

# log配置字典
LOGGING_DIC = {
    'version': 1,
    'disable_existing_loggers': False,
    'formatters': {
        'standard': {
            'format': standard_format
        },
        'simple': {
            'format': simple_format,
            'datefmt': "%Y-%m-%d %H:%M:%S"
        },
    },
    'filters': {},
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'default': {
            'level': 'DEBUG',
            'class': 'ser_log.my_handler.TimeHandler',
            'formatter': 'standard',
            'name': 'socket',
            'file_path': logfile_dir,
            'when': 'D',
            'backupCount': 14,
            'delay': True,
            'encoding': 'utf-8',
        }
    },
    'loggers': {
        'generate': {
            'handlers': ['default', 'console'],
            'level': 'DEBUG',
            'propagate': True,
        }
    },
}
自定义handler - my_handler.py
import os
import datetime
from logging.handlers import WatchedFileHandler


class TimeHandler(WatchedFileHandler):
    # 支持多进程的TimeHandler
    def __init__(self, name, file_path, backupCount=3, mode='a', when='D', encoding=None, delay=False):
        if not os.path.exists(file_path):
            os.makedirs(file_path)
        self._file_name = name
        self.file_path = file_path
        self.backupCount = backupCount if backupCount > 3 else 3
        self.when = when.upper()
        self.when_dict = {
            'S': "%Y-%m-%d-%H-%M-%S",
            'M': "%Y-%m-%d-%H-%M",
            'H': "%Y-%m-%d-%H",
            'D': "%Y-%m-%d"
        }
        self.file_name = "{}_{}.log".format(self._file_name, datetime.datetime.now().strftime(self.when_dict.get(self.when,'D')))
        filename = os.path.join(self.file_path, self.file_name)
        super().__init__(filename=filename, mode=mode,encoding=encoding, delay=delay)

    def doChangeFile(self):
        if self.stream:
            self.stream.close()
            self.stream = None
        if not self.delay:
            self.stream = self._open()
        if self.backupCount > 0:
            for s in self.getFilesToDelete():
                print(f'remove :{s}')
                os.remove(s)

    def getFilesToDelete(self):
        fileNames = os.listdir(self.file_path)
        result = []
        for fileName in fileNames:
            if fileName.startswith(f"{self._file_name}_{datetime.datetime.now().strftime(self.when_dict.get(self.when,'D'))}"):
                result.append(os.path.join(self.file_path, fileName))
        result.sort()
        if len(result) <= self.backupCount:
            result = []
        else:
            result = result[:len(result) - self.backupCount]
        return result

    def emit(self, record):
        current_file_name = "{}_{}.log".format(self._file_name,datetime.datetime.now().strftime(self.when_dict.get(self.when,'D')))
        if current_file_name != self.file_name:
            self.doChangeFile()
            self.file_name = current_file_name
            self.baseFilename = os.path.abspath(os.path.join(self.file_path, self.file_name))
            if self.stream:
                self.stream.flush()
                self.stream.close()
            self.stream = self._open()
            self._statstream()
        self.reopenIfNeeded()
        super().emit(record)
入口文件 - run.py
import pickle
import logging
import logging.handlers
import socketserver
import struct


class LogRecordStreamHandler(socketserver.StreamRequestHandler):
    """
    流式日志记录请求的处理程序。
    这基本上使用任何日志记录策略记录记录
    本地配置。
    """

    def handle(self):
        """
        处理多个请求 - 每个请求的长度为 4 字节,
        然后是pickle格式的LogRecord。 记录记录
        根据本地配置的任何策略。
        """
        while True:
            chunk = self.connection.recv(4)
            if len(chunk) < 4:
                break
            slen = struct.unpack('>L', chunk)[0]
            chunk = self.connection.recv(slen)
            while len(chunk) < slen:
                chunk = chunk + self.connection.recv(slen - len(chunk))
            obj = self.unPickle(chunk)
            record = logging.makeLogRecord(obj)
            self.handleLogRecord(record)

    def unPickle(self, data):
        return pickle.loads(data)

    def handleLogRecord(self, record):
        # 获取远程使用的logger名字
        if self.server.logname is not None:
            name = self.server.logname
        else:
            name = record.name
        # 创建对于的logger实例化
        logger = logging.getLogger(name)
        logger.handle(record)


class LogRecordSocketReceiver(socketserver.ThreadingTCPServer):
    """
    Simple TCP socket-based logging receiver suitable for testing.
    """
    allow_reuse_address = True

    # 绑定ip和端口
    # logging.handlers.DEFAULT_TCP_LOGGING_PORT是9020端口
    def __init__(self, host='localhost',
                 port=logging.handlers.DEFAULT_TCP_LOGGING_PORT,
                 handler=LogRecordStreamHandler):
        socketserver.ThreadingTCPServer.__init__(self, (host, port), handler)
        self.abort = 0
        self.timeout = 1
        self.logname = None

    def serve_until_stopped(self):
        import select
        abort = 0
        while not abort:
            rd, wr, ex = select.select([self.socket.fileno()],
                                       [], [],
                                       self.timeout)
            if rd:
                self.handle_request()
            abort = self.abort


def main():
    import logging.config
    from ser_log import conf
    # 配置日志
    logging.config.dictConfig(conf.LOGGING_DIC)
    tcpserver = LogRecordSocketReceiver()
    print('About to start TCP server...')
    tcpserver.serve_until_stopped()


if __name__ == '__main__':
    main()
# 服务端控制台打印
About to start TCP server...
2022-06-18 17:59:41  DEBUG    clin.py:19    我是客户端日志
# 服务端log文件
[2022-06-18 17:59:41,694] [DEBUG] [MainThread 8663756288] [clin.py:19] 我是客户端日志

客户端

client.py
import logging
import logging.handlers

generateLogger = logging.getLogger(f'generate')
generateLogger.setLevel(logging.DEBUG)
# 创建SocketHandler
socketHandler = logging.handlers.SocketHandler('127.0.0.1', 9020)

# 创建simpleHandler
simpleHandler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)-20s %(levelname)-8s %(filename)-5s:%(lineno)-5d %(message)s')
simpleHandler.setFormatter(formatter)

# rootLogger绑定Handler对象
generateLogger.addHandler(socketHandler)
generateLogger.addHandler(simpleHandler)

# 发送日志
generateLogger.debug(f'我是客户端日志')
# 客户端控制台打印
2022-06-18 17:59:41,694 DEBUG    clin.py:19    我是客户端日志
客户端发送多个socket及注意事项

logging.getLogger()没有name值默认获取root

import os, time
from multiprocessing import Process, Pool

import logging
import logging.handlers

# 创建rootLogger
rootLogger = logging.getLogger()
rootLogger.setLevel(logging.DEBUG)

# 创建Handler
# 网络输出
socketHandler1 = logging.handlers.SocketHandler('127.0.0.1', logging.handlers.DEFAULT_TCP_LOGGING_PORT)
socketHandler2 = logging.handlers.SocketHandler('127.0.0.2', logging.handlers.DEFAULT_TCP_LOGGING_PORT)
# 屏幕输出
simpleHandler = logging.StreamHandler()

# 绑定两个socket
rootLogger.addHandler(socketHandler1)
rootLogger.addHandler(socketHandler2)
rootLogger.addHandler(simpleHandler)


def run_a_sub_proc(name, age):
    rootLogger.info('root>>>')
    # 配置给rootLogger设置的,其他实例化的也都有效
    # logging.getLogger([name]) # 这个name需要和服务端对于,这样服务端才会记录
    generate_logger = logging.getLogger('generate')
    generate_logger.debug("姓名 %s, 年龄%d", name, age)
    generate_logger.info("姓名 %s, 年龄%d" % (name, age))
    generate_logger.debug("姓名 {}, 年龄{}".format(name, age))
    generate_logger.error(f"姓名{name}, 年龄{age}")
    generate_logger.warning(f"姓名{name}, 年龄{age}")
    generate_logger.critical(f"姓名{name}, 年龄{age}")


if __name__ == '__main__':
    print(f'主进程({os.getpid()})开始...')
    p = Pool(3)
    for i in range(1, 10):
        p.apply_async(run_a_sub_proc, args=(i, i + 1))
    p.close()
    p.join()
posted @ 2022-06-18 18:36  lxd670  阅读(18)  评论(0编辑  收藏  举报