Обновить свойство в синглтоне (python) - PullRequest
0 голосов
/ 14 сентября 2018

EDIT: добавлена ​​рекомендация Ральфа использовать 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».Как мне это исправить?

1 Ответ

0 голосов
/ 14 сентября 2018

Вы даете очень мало конкретных деталей, поэтому я дам ответ, который должен сработать, но я не знаю, если вы этого хотели.

Как насчет сохранения текущего имени файла в переменной окружения с помощью 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'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...