日志记录
使用basicConfig
import logging
# 配置日志记录系统的基本设置
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 获取一个日志记录器
logger = logging.getLogger('simple_example')
# 记录不同级别的日志信息
logger.debug('This is a debug message') # 这条消息不会被输出,因为级别低于设置的级别
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')
输出为:
2024-09-17 14:10:31,787 - simple_example - INFO - This is an info message
2024-09-17 14:10:31,788 - simple_example - WARNING - This is a warning message
2024-09-17 14:10:31,788 - simple_example - ERROR - This is an error message
2024-09-17 14:10:31,788 - simple_example - CRITICAL - This is a critical message
在 Python 的 logging`模块中,basicConfig 函数用于配置日志系统的基本设置。你提供的代码行是设置日志记录的格式和级别。这四个参数分别是:
-
level=logging.INFO: 这是日志级别。logging.INFO表示只有 INFO 级别及以上(WARNING, ERROR, CRITICAL)的日志消息会被处理。日志级别从低到高依次是:DEBUG, INFO, WARNING, ERROR, CRITICAL。
-
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s': 这是日志消息的格式。这个格式字符串定义了日志消息的外观。其中包含的各个部分是:
- %(asctime)s: 日志事件发生的时间。默认格式是 `年-月-日 时:分:秒,毫秒`。
- %(name)s: 记录日志的记录器的名称。
- %(levelname)s: 日志级别的名称(如 INFO, ERROR)。
- %(message)s: 记录器传递给 `log` 方法的实际日志消息。
-
datefmt=None: 这个参数在代码中没有显示,但它是 `basicConfig` 的另一个参数,用于指定 `asctime` 的日期格式。如果没有设置,将使用默认格式。
-
style='%': 这也是一个可选参数,用于指定格式化字符串中的样式。默认是 `%`,这意味着使用传统的 `%` 格式化。
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
这行代码的作用是设置日志系统,使得所有 INFO 级别及以上的日志消息都会被记录,并且按照指定的格式输出。
使用Formatter
import logging
# 创建一个日志记录器
logger = logging.getLogger('simple_example')
logger.setLevel(logging.WARNING) # 设置日志级别为WARNING,这意味着只有级别为WARNING及以上的日志才会被记录
# 创建一个日志格式器
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 创建一个控制台处理器,并设置级别和格式
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.WARNING)
console_handler.setFormatter(formatter)
# 将处理器添加到日志记录器
logger.addHandler(console_handler)
# 记录几条不同级别的日志消息
logger.warning('这是一个 warning 级别的日志信息')
logger.error('这是一个 error 级别的日志信息')
logger.critical('这是一个 critical 级别的日志信息')
StreamHandler
是 Pythonlogging
模块中的一个处理器(handler),用于将日志消息输出到流中,通常是标准输出(控制台)。
Formatter和basicConfig功能类似,区别如下:
- 使用场景 :
basicConfig
通常用于快速设置全局日志配置,而Formatter
用于更精细的控制,比如为不同的日志处理器设置不同的格式。 - 灵活性 :使用
Formatter
类可以更灵活地为不同的日志处理器设置不同的格式,而basicConfig
则一次性设置全局配置。 - 配置方式 :
basicConfig
是函数调用,而Formatter
是通过创建对象并设置到处理器上来配置。
FileHandler
import logging
# 创建一个日志记录器
logger = logging.getLogger('file_handler_example')
logger.setLevel(logging.DEBUG) # 设置日志级别为DEBUG
# 创建一个日志格式器
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 创建一个文件处理器,指定日志文件的名称
file_handler = logging.FileHandler('example.log')
file_handler.setLevel(logging.INFO) # 设置文件处理器的日志级别为INFO
file_handler.setFormatter(formatter) # 将格式器应用到文件处理器
# 将文件处理器添加到日志记录器
logger.addHandler(file_handler)
# 记录几条不同级别的日志消息
logger.debug('这是一个 debug 级别的日志信息')
logger.info('这是一个 info 级别的日志信息')
logger.warning('这是一个 warning 级别的日志信息')
logger.error('这是一个 error 级别的日志信息')
logger.critical('这是一个 critical 级别的日志信息')
这样便可以将日志输出到文件内了。
总结
-
日志记录器(Logger) :
logger = logging.getLogger('file_handler_example')
创建了一个日志记录器对象,'file_handler_example'
是这个记录器的名称。 -
日志级别(Level) :
logger.setLevel(logging.DEBUG)
设置了日志记录器的级别为DEBUG
,这意味着所有DEBUG
及以上级别的日志消息都会被处理。 -
日志格式器(Formatter) :
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
创建了一个日志格式器对象,定义了日志消息的格式。在这个格式中,%(asctime)s
表示时间戳,%(name)s
表示记录器的名称,%(levelname)s
表示日志级别,%(message)s
表示日志消息。 -
文件处理器(FileHandler) :
file_handler = logging.FileHandler('example.log')
创建了一个文件处理器对象,指定了日志文件的名称为example.log
。file_handler.setLevel(logging.INFO)
设置了文件处理器的日志级别为INFO
,这意味着所有INFO
及以上级别的日志消息都会被写入文件。 -
添加处理器(Add Handler) :
logger.addHandler(file_handler)
将文件处理器添加到日志记录器中,这样日志记录器就会通过这个处理器将日志消息写入文件。 -
记录日志(Logging) :
logger.debug(...)
、logger.info(...)
等方法用于记录不同级别的日志消息。在这个例子中,只有INFO
及以上级别的日志消息会被写入文件,因为文件处理器的级别被设置为INFO
。
命令行交互
基础用法
import argparse
# 创建 ArgumentParser 对象
parser = argparse.ArgumentParser(description='Multiply a number by a given value.')
# 添加位置参数
parser.add_argument('number', type=int, help='The number to multiply')
# 添加可选参数 --multiply
parser.add_argument('--multiply', type=int, default=1, help='The value to multiply the number by')
# 解析命令行参数
args = parser.parse_args()
# 计算乘积
product = args.number * args.multiply
# 输出结果
print(f'The result is: {product}')
输出:
PS E:\StudyAndWork\Courses\Senior\graduate\compresscode_all\PyTorchVideoCompression-master\DVC> python TryParse.py 5
The result is: 5
PS E:\StudyAndWork\Courses\Senior\graduate\compresscode_all\PyTorchVideoCompression-master\DVC> python TryParse.py 5 --multiply 5
The result is: 25
在 Python 中,argparse
模块是用于处理命令行参数和选项的标准库。ArgumentParser
是 argparse
模块中的一个类,它提供了一个易于使用的接口来处理命令行参数。
parser = argparse.ArgumentParser(description='Multiply a number by a given value.')
argparse.ArgumentParser
: 这是创建一个新的解析器对象的方法。解析器对象负责解析命令行参数。
description
: 这是一个可选参数,用于提供程序的简短描述。这个描述会在自动生成的帮助和使用说明中显示。
这行代码创建了一个 ArgumentParser
对象,命名为 parser
。这个对象可以用来定义程序接受哪些命令行参数,以及如何解析这些参数。
接下来,你可以使用 parser
对象来添加参数,例如:
# 添加位置参数
parser.add_argument('number', type=int, help='The number to multiply')
# 添加可选参数 --multiply
parser.add_argument('--multiply', type=int, default=1, help='The value to multiply the number by')
这里,add_argument
方法用于添加两个位置参数:number
和 --multiply
。每个参数都有一个 type
,指定了参数应该被解析为哪种类型(在这个例子中是 float
),以及一个 help
字符串,描述了每个参数的作用。
其中multiply是可选参数,如果不传入,就会使用默认值。
最后,你可以使用 parse_args()
方法来解析命令行参数:
args = parser.parse_args()
这将解析命令行参数,并返回一个包含参数值的命名空间对象。
action
在 argparse
模块中,action
参数定义了当命令行参数被解析时应该采取的操作。不同的 action
值会影响如何处理参数和如何更新解析后的参数值。以下是一些常用的 action
值及其用途:
-
store
(默认): 这是默认的action
,它简单地将命令行参数的值存储在解析后的参数对象中。如果参数是可选的,并且没有提供值,则其值将为None
。如果提供了值,则其值将为提供的值。parser.add_argument('--option', type=str, action='store', help='Some option')
-
store_true
: 这个action
用于开关参数,它不需要值。如果命令行中出现了这个参数,那么在解析后的参数对象中,该参数的值将被设置为True
。parser.add_argument('--verbose', action='store_true', help='Increase output verbosity')
-
store_false
: 类似于store_true
,但它用于设置参数值为False
。如果命令行中出现了这个参数,那么在解析后的参数对象中,该参数的值将被设置为False
。parser.add_argument('--quiet', action='store_false', help='Decrease output verbosity')
-
append
: 这个action
用于将参数的值添加到一个列表中。如果同一个参数在命令行中出现多次,它的值将被收集到一个列表中。parser.add_argument('--item', action='append', help='An item to add to a list')
-
append_const
: 这个action
用于将一个常量值添加到列表中。通常与const
参数一起使用,表示无论命令行中参数的值是什么,都添加const
指定的值。parser.add_argument('--enable', action='append_const', const='ENABLE', help='Enable a feature')
-
count
: 这个action
用于计数某个参数在命令行中出现的次数。这通常用于设置日志级别或增加输出的详细程度。parser.add_argument('--v', action='count', help='Increase verbosity level')
-
help
: 这个action
用于显示帮助信息并退出程序。通常与-h
或--help
参数一起使用。parser.add_argument('--help', action='help', help='Show this help message and exit')
-
version
: 这个action
用于显示程序的版本信息并退出程序。通常与--version
参数一起使用。parser.add_argument('--version', action='version', version='%(prog)s 1.0', help='Show program version')
-
extend
: 类似于append
,但这个action
用于将参数的值扩展到一个列表中。如果参数的值是一个列表或元组,它的每个元素都将被添加到解析后的参数对象的列表中。parser.add_argument('--options', action='extend', nargs='+', help='Options to extend')
通过使用不同的 action
值,你可以创建灵活和强大的命令行接口,以满足各种不同的需求。
长短参数的传递
在 argparse
模块中,短选项(如 -l
)通常是长选项(如 --log
)的简写形式。它们都关联到同一个参数,用户可以根据自己的喜好选择使用短选项或长选项来传递参数值。
假设你有一个脚本 train.py
,定义了两个参数:
import argparse
# 创建 ArgumentParser 对象
parser = argparse.ArgumentParser(description='Train a model with optional pretraining and logging.')
# 添加命令行参数
parser.add_argument('-l', '--log', default='',
help='output training details to a file')
parser.add_argument('-p', '--pretrain', default='',
help='load pretrained model')
# 解析命令行参数
args = parser.parse_args()
# 使用参数
if args.log:
print(f'Logging output to {args.log}')
if args.pretrain:
print(f'Loading pretrained model from {args.pretrain}')
# 模拟训练过程
print('Training model...')
用户可以使用短选项或长选项来运行脚本:
python train.py -l logfile.txt # 使用短选项
python train.py --log logfile.txt # 使用长选项
两种方式都会将 --log
参数的值设置为 "logfile.txt"
。
同样,对于预训练模型的参数:
python train.py -p pretrained_model.pth # 使用短选项
python train.py --pretrain pretrained_model.pth # 使用长选项
两种方式都会将 --pretrain
参数的值设置为 "pretrained_model.pth"
。
短选项和长选项都是同一种参数的不同表现形式,它们在 argparse
中关联到同一个参数对象。用户可以根据自己的习惯和需求选择使用哪一种。这种设计使得命令行接口更加灵活和用户友好。