我想使用Python的日志库来覆盖之前的控制台行。当进程运行时,它应该在控制台上显示
...
,然后在进程完成后用 OK
覆盖它,如此 Python 代码所示。
import time
for i in range(10):
print(f'Progress: {i+1}/10 ...', end='')
time.sleep(1)
print(f'\rProgress: {i+1}/10 OK')
我想使用
logging
库实现相同的结果,但我当前的解决方案感觉太冗长且不符合 Python 风格。有人有更好的方法吗?谢谢!
import logging
import sys
import time
class OverwriteStreamHandler(logging.StreamHandler):
def __init__(self, stream, overwrite=False):
super().__init__(stream)
self.overwrite = overwrite
def emit(self, record):
msg = self.format(record)
stream = self.stream
if self.overwrite:
stream.write('\r' + msg)
else:
stream.write(msg)
stream.flush()
def create_logger(name, overwrite=False):
handler = OverwriteStreamHandler(sys.stdout, overwrite=overwrite)
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(message)s')
handler.setFormatter(formatter)
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)
return logger
logger1 = create_logger('logger1')
logger2 = create_logger('logger2', overwrite=True)
for i in range(10):
logger1.info(f'Progress: {i+1}/10 ...')
time.sleep(1)
logger2.info(f'Progress: {i+1}/10 Ok\n')
有2个选择: 1-添加带有空终止符的处理程序并手动添加行终止符。 2- 创建一个附加记录器,并在处理程序中配置终止符。
import logging
import time
logging.basicConfig(level=logging.INFO)
logger1 = logging.getLogger("SO_log")
logger2 = logging.getLogger("SO_log")
ch = logging.StreamHandler()
ch.terminator=''
ch.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger2.addHandler(ch)
logger2.propagate = False
logger1.info('Started\n')
for i in range(10):
msg = f'Progress: {i+1:>2}/10 {"..."}\r'
logger1.info(msg)
time.sleep(0.21)
msg = f'Progress: {i+1:>2}/10 {"Ok":>3}\r'
if i == 10:
msg += "\n"
logger1.info(msg)
# additional delay to get a chance to see the Ok msg
time.sleep(0.21)
logger1.info('\n')
输出日期和消息的最后 9 个字符将交替出现
2024-12-18 23:44:32,535 - SO_log1 - INFO - Started
2024-12-18 23:44:34,638 - SO_log1 - INFO - Progress: 10/10 Ok
使用 2 个记录器并在处理程序上设置行终止符
import logging
import time
logging.basicConfig(level=logging.INFO)
logger1 = logging.getLogger("SO_log1")
logger2 = logging.getLogger("SO_log2")
ch1 = logging.StreamHandler()
ch1.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch1.setFormatter(formatter)
logger1.addHandler(ch1)
logger1.propagate = False
ch2 = logging.StreamHandler()
ch2.terminator='\r'
ch2.setLevel(logging.INFO)
ch2.setFormatter(formatter)
logger2.addHandler(ch2)
logger2.propagate = False
logger1.info('Started opt 2')
for i in range(10):
msg = f'Progress: {i+1:>2}/10 {"..."}'
logger2.info(msg)
time.sleep(0.21)
msg = f'Progress: {i+1:>2}/10 {"Ok":>3}'
#logger2.info(msg)
if i < 10:
logger2.info(msg)
else:
logger1.info(msg)
time.sleep(0.21)
logger1.info("\n")
输出2
2024-12-19 00:03:38,262 - SO_log1 - INFO - Started opt 2
2024-12-19 00:03:42,467 - SO_log1 - INFO - Progress: 10/10 Ok