以singleton(python)更新属性

问题描述 投票:2回答:1

编辑:添加了Ralf建议使用os.environ

尝试实现单例记录器,以便每次生成记录器实例时,它只会写入特定的文件名。直到指定新文件名。

import logging

def singleton(myClass):                                             
    instances = {}                                                  
    def getInstance(*args,**kwargs):
        if myClass not in instances:
           instances[myClass] = myClass(*args,**kwargs)         
        return instances[myClass]                                   
    return getInstance                                              

@singleton
class Logger(object):
    def __init__(self):
        self.filename = os.environ['logger_filename']
        self.log = self.init_logger()

    def init_logger(self):
        fh = logging.FileHandler(self.filename + '.log')
        fmt = logging.Formatter("%(asctime)-6s: %(name)s - %(levelname)s - %(message)s)")
        fh.setFormatter(fmt)
        local_logger = logging.getLogger(self.filename)
        local_logger.setLevel(logging.DEBUG)
        local_logger.addHandler(fh)

        return local_logger

我上面的内容总是写在“test1.log”文件中。

os.environ['logger_filename'] = "test1"

a = Logger()
b = Logger()

a.log.debug("Hello A")
b.log.debug("Hello B")

os.environ['logger_filename'] = "test2"

c = Logger()
c.log.debug("Hello C")

由于单例将在实例中包含Logger类,因此它将只返回该实例而不运行__init__

如果我使用以下内容更新单例:

def singleton(myClass):
    instances = {}
    def getInstance(*args,**kwargs):
        if myClass not in instances:
           instances[myClass] = myClass(*args,**kwargs)
        else:
            instances[myClass].update_logger()
        return instances[myClass]
    return getInstance

@singleton
class Logger(object):
    def __init__(self):
        self.filename = os.environ['logger_filename']
        self.log = self.init_logger()

    def init_logger(self):
        fh = logging.FileHandler(self.filename + '.log')
        fmt = logging.Formatter("%(asctime)-6s: %(name)s - %(levelname)s - %(message)s)")
        fh.setFormatter(fmt)
        local_logger = logging.getLogger(self.filename)
        local_logger.setLevel(logging.DEBUG)
        local_logger.addHandler(fh)

        return local_logger

    def update_logger(self):
        self.filename = os.environ['logger_filename']
        self.log = self.init_logger()


os.environ['logger_filename'] = "test1"


a = Logger()
b = Logger()

a.log.debug("Hello A")
b.log.debug("Hello B")

os.environ['logger_filename'] = "test2"

c = Logger()
c.log.debug("Hello C")

这将生成2个日志文件(test1和test2)。但test1将包含两个“Hello A”和两个“Hello B”。我如何解决这个问题?

python singleton
1个回答
2
投票

你提供的细节很少,所以我会给出一个应该有效的答案,但我不知道这是不是你想要的。

如何使用os.environ将当前文件名存储在环境变量中?

你可以修改singleton函数:

import os

def singleton(myClass):                                             
    ...
        if myClass not in instances:
           kwargs['filename'] = os.environ['logger_filename']  # may raise KeyError
           instances[myClass] = myClass(*args, **kwargs)         
    ...

@singleton
class Logger(object):
    def __init__(self, filename):
        self.filename = filename
    ...

或者另一种选择是只修改记录器类:

import os

@singleton
class Logger(object):
    def __init__(self):
        self.filename = os.environ['logger_filename']  # may raise KeyError

使用这两个选项中的任何一个,您只需修改环境变量的值即可为记录器设置不同的目标:

import os
os.environ['logger_filename'] = 'f1.log'

b = Logger() 
b.log.debug("hello there")    # writes on 'f1.log'

os.environ['logger_filename'] = 'f2222.log'

c = Logger() 
c.log.debug("hello there")    # writes on 'f2222.log'
© www.soinside.com 2019 - 2024. All rights reserved.