代码之家  ›  专栏  ›  技术社区  ›  user1179317

在singleton(python)中更新属性

  •  2
  • user1179317  · 技术社区  · 6 年前

    编辑:增加了拉尔夫的建议使用操作系统环境

    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")
    

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

    如果我用以下内容更新singleton:

    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将包含两个“helloa”和两个“hellob”。我该怎么解决这个问题?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Ralf    6 年前

    你很少给出具体的细节,所以我会给出一个可行的答案,但我不知道这是否是你想要的。

    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
        ...
    

    或者另一个选项是只修改logger类:

    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'