如何更改文件句柄与Python与不同类别的进口飞登录(How to change filehandl

2019-07-05 01:11发布

我不能执行上的即时记录文件句柄的变化。

例如,我有3个班

one.py

import logging
class One():
    def __init__(self,txt="?"):
        logging.debug("Hey, I'm the class One and I say: %s" % txt)

two.py

import logging
class Two():
    def __init__(self,txt="?"):
        logging.debug("Hey, I'm the class Two and I say: %s" % txt)

config.py

import logging
class Config():
    def __init__(self,logfile=None):
        logging.debug("Reading config")
        self.logfile(logfile)

myapp

from one import One
from two import Two
from config import Config
import logging

#Set default logging
logging.basicConfig( 
    level=logging.getLevelName(DEBUG), 
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    filename=None
)

logging.info("Starting with stdout")

o=One(txt="STDOUT")
c=Config(logfile="/tmp/logfile")

# Here must be the code that change the logging configuration and set the filehandler

t=One(txt="This must be on the file, not STDOUT")

如果我尝试loggin.basicConfig()再次,这是行不通的。

Answer 1:

事实上, logging.basicConfig 什么都不做 ,如果处理程序已经成立已:

这个函数做什么,如果根记录器已经为它配置了处理程序。

你将需要更换的根记录当前的处理程序:

import logging

fileh = logging.FileHandler('/tmp/logfile', 'a')
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fileh.setFormatter(formatter)

log = logging.getLogger()  # root logger
for hdlr in log.handlers[:]:  # remove all old handlers
    log.removeHandler(hdlr)
log.addHandler(fileh)      # set the new handler

请参阅配置日志章在Python记录HOWTO。



Answer 2:

我发现比上面的“接受”的答案更简单的方法。 如果你有处理程序的引用,所有你需要做的是调用close()方法,然后设置baseFilename属性。 当您指定baseFilename,一定要使用os.path.abspath则()。 有一个在库源表示需要它的评论。 我一直在全球的dict()我的配置的东西,所以很容易保持的FileHandler参考对象。 正如你可以看到下面,只需要2行代码更改日志文件名在飞行的处理程序。

import logging

def setup_logging():
  global config

  if config['LOGGING_SET']:
    config['LOG_FILE_HDL'].close()
    config['LOG_FILE_HDL'].baseFilename = os.path.abspath(config['LOG_FILE'])

    config['DEBUG_LOG_HDL'].close()
    config['DEBUG_LOG_HDL'].baseFilename = os.path.abspath(config['DEBUG_LOG'])
  else:
    format_str = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    formatter = logging.Formatter(format_str)

    log = logging.getLogger()

    log.setLevel(logging.DEBUG)

    # add file mode="w" to overwrite
    config['LOG_FILE_HDL'] = logging.FileHandler(config['LOG_FILE'], mode='a')
    config['LOG_FILE_HDL'].setLevel(logging.INFO)
    config['LOG_FILE_HDL'].setFormatter(formatter)
    log.addHandler(config['LOG_FILE_HDL'])

    # the delay=1 should prevent the file from being opened until used.
    config['DEBUG_LOG_HDL'] = logging.FileHandler(config['DEBUG_LOG'], mode='a', delay=1)
    config['DEBUG_LOG_HDL'].setLevel(logging.DEBUG)
    config['DEBUG_LOG_HDL'].setFormatter(formatter)
    log.addHandler(config['DEBUG_LOG_HDL'])

    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    ch.setFormatter(formatter)
    log.addHandler(ch)
    config['LOGGING_SET'] = True


Answer 3:

通过@Martijn皮特斯提供的答案做工不错。 但是,代码剪断删除所有处理程序,并放置只有文件句柄回来。 如果你的应用有其他模块添加的处理程序,这将是麻烦。

因此,下面的代码段的设计以这样的方式只替换文件处理程序。

该生产线if isinstance(hdlr,log.FileHander)是关键。

import logging

filehandler = logging.FileHandler('/tmp/logfile', 'a')
formatter = logging.Formatter('%(asctime)-15s::%(levelname)s::%(filename)s::%(funcName)s::%(lineno)d::%(message)s')
filehandler.setFormatter(formatter)
log = logging.getLogger()  # root logger - Good to get it only once.
for hdlr in log.handlers[:]:  # remove the existing file handlers
    if isinstance(hdlr,log.FileHander):
        log.removeHandler(hdlr)
log.addHandler(filehandler)      # set the new handler
# set the log level to INFO, DEBUG as the default is ERROR
logging.setLevel(log.DEBUG)      


Answer 4:

我试图执行此页面上的建议,由@Martijn皮特斯与@Arun Thundyill Saseendran结合。 我太新被允许发表评论,所以我要发布调整后的答案。 在isinstance电话,我不得不用,而不是“登录”“记录”来获得访问类型(日志是一个实例),然后在“FileHander”应该“的FileHandler”。 我使用Python 3.6。

import logging

filehandler = logging.FileHandler('/tmp/logfile', 'a')
formatter = logging.Formatter('%(asctime)-15s::%(levelname)s::%(filename)s::%(funcName)s::%(lineno)d::%(message)s')
filehandler.setFormatter(formatter)
log = logging.getLogger()  # root logger - Good to get it only once.
for hdlr in log.handlers[:]:  # remove the existing file handlers
    if isinstance(hdlr,logging.FileHandler): #fixed two typos here
        log.removeHandler(hdlr)
log.addHandler(filehandler)      # set the new handler
# set the log level to INFO, DEBUG as the default is ERROR
logging.setLevel(log.DEBUG)      


文章来源: How to change filehandle with Python logging on the fly with different classes and imports