我有一个日志配置,我在其中登录文件和控制台:
logging.basicConfig(filename=logfile, filemode='w',
level=numlevel,
format='%(asctime)s - %(levelname)s - %(name)s:%(funcName)s - %(message)s')
# add console messages
console = logging.StreamHandler()
console.setLevel(logging.INFO)
consoleformatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
console.setFormatter(consoleformatter)
logging.getLogger('').addHandler(console)
在我的脚本中的某个时刻,我需要通过打印摘要并要求确认来与用户进行交互。摘要目前由循环中的打印产生。我想暂停当前控制台日志的格式,这样我就可以打印出一大块文本,并在最后输出一个问题并等待用户输入。但我仍然希望将所有这些记录到文件中!
执行此操作的功能位于模块中,我尝试了以下操作:
logger = logging.getLogger(__name__)
def summaryfunc:
logger.info('normal logging business')
clearformatter = logging.Formatter('%(message)s')
logger.setFormatter(clearformatter)
logger.info('\n##########################################')
logger.info('Summary starts here')
产生错误:AttributeError: 'Logger' object has no attribute 'setFormatter'
我知道记录器是记录器,而不是处理程序,但我不确定如何让事情发挥作用......
编辑:
根据答案,我的问题变成:如何在与用户交互时暂停登录到控制台,同时仍然能够登录到文件。 IE:只挂起streamHandler。由于这是在一个模块中发生的,处理程序的细节在其他地方定义,所以这就是我如何做到的:
logger.debug('Normal logging to file and console')
root_logger = logging.getLogger()
stream_handler = root_logger.handlers[1]
root_logger.removeHandler(stream_handler)
print('User interaction')
logger.info('Logging to file only')
root_logger.addHandler(stream_handler)
logger.info('Back to logging to both file and console')
这依赖于streamHandler始终是handlers
返回的列表中的第二个,但我相信这是因为它是按照我将处理程序添加到根记录器的顺序...
答案 0 :(得分:4)
我同意Vinay您应该使用print
进行正常的程序输出,并且仅使用logging
进行日志记录。但是,如果您仍想在中间切换格式,请切换回来,以下是如何操作:
import logging
def summarize():
console_handler.setFormatter(logging.Formatter('%(message)s'))
logger.info('Here is my report')
console_handler.setFormatter(console_formatter)
numlevel = logging.DEBUG
logfile = 's2.log'
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
console_handler = logging.StreamHandler()
console_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
console_handler.setFormatter(console_formatter)
logger.addHandler(console_handler)
file_handler = logging.FileHandler(filename=logfile, mode='w')
file_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s:%(funcName)s - %(message)s')
file_handler.setFormatter(file_formatter)
logger.addHandler(file_handler)
logger.info('Before summary')
summarize()
logger.info('After summary')
summarize()
中,我为控制台处理程序切换了一个新格式化程序,执行了一些日志记录,然后切换回来。logging
来显示正常的节目输出。如果要禁止控制台日志记录,请将其重新打开。这是一个建议:
def interact():
# Remove the console handler
for handler in logger.handlers:
if not isinstance(handler, logging.FileHandler):
saved_handler = handler
logger.removeHandler(handler)
break
# Interact
logger.info('to file only')
# Add the console handler back
logger.addHandler(saved_handler)
请注意,我没有针对logging.StreamHandler
测试处理程序,因为logging.FileHandler
来自logging.StreamHandler
。因此,我删除了那些不是FileHandler
的处理程序。在删除之前,我保存了该处理程序以便以后恢复。
在主脚本中,如果您有:
logger = logging.getLogger(__name__) # __name__ == '__main__'
然后在一个模块中,你做:
logger = logging.getLogger(__name__) # __name__ == module's name, not '__main__'
问题是,在脚本__name__ == '__main__'
和模块中,__name__ == <the module's name>
而不是'__main__'
。为了实现一致性,您需要在两个地方组成一些名称并使用它们:
logger = logging.getLogger('MyScript')
答案 1 :(得分:3)
不应使用记录来提供程序的实际输出 - 如果完全关闭记录,程序应该以相同的方式运行。所以我建议你最好先做你以前做过的事情,比如在循环中打印。