Как использовать модуль «регистрации» в библиотеке, обеспечивая при этом простой интерфейс для пользователей библиотеки?Python

Программы на Python
Гость
Как использовать модуль «регистрации» в библиотеке, обеспечивая при этом простой интерфейс для пользователей библиотеки?

Сообщение Гость »

Я разрабатываю библиотеку Python, которая определяет следующие классы:
  • класс контроллера
  • класс BaseManager и несколько дочерних классов BaseManagerXxx
Контроллер создает экземпляры менеджеров, а затем запускает их (make они что-то делают). Пользовательское приложение, использующее эту библиотеку, обычно реализует новые классы, наследуемые от классов BaseManagerXxx, создает экземпляр одного контроллера, указывая экземпляры менеджеров, которые нужно создать, и запускает этот контроллер. Пример минимального кода следующий:

Код: Выделить всё

#---------------------------------------------------
# Library code
#---------------------------------------------------

class Controller:

def __init__(self,managerinfo):
self.managers = [mtype(mname) for mtype,mname in managerinfo]

def run(self):
# do something with managers, for instance:
self.managers[0].parseStuff()
self.managers[1].cleanStuff()

class BaseManager:
def __init__(self,name):
self.name = name
def parseStuff(self):
pass #something is actually done here
def cleanStuff(self): # example only
pass #something is actually done here

class BaseManager1: BaseManager:
pass # actually redefine some base methods
class BaseManager2: BaseManager:
pass # actually redefine some base methods
Код пользовательского приложения может быть примерно таким:

Код: Выделить всё

#---------------------------------------------------
# User app code
#---------------------------------------------------
from the_library import *
from another_user_module import ARandomClass

class MyManager1: BaseManager1
def parseStuff(self):
c = ARandomClass()  #might also log messages or raise exceptions
print("WARNING: something might be wrong")

class MyManager2: BaseManager2
def cleanStuff(self):
raise RuntimeError("Something is seriously wrong here")

c = Controller([
(MyManager1,"foo"),
(MyManager2,"bar")])
c.run()
На данный момент журналирование осуществляется с помощью операторов печати с сильно разнородными стилями из-за того, что разные пользователи разрабатывают специальные менеджеры для одного и того же приложения. Я хочу использовать модуль «регистрации» для обеспечения единообразия и применить общий стиль ко всем журналам, выполняемым каждой частью приложения. Более того, я хочу, чтобы все исключения перехватывались и приводили к созданию сообщения журнала в том же стиле.
Точнее:
  • Каждый журнал должен содержать имя менеджера, в котором в данный момент выполняется выполнение (или пустую строку, если мы находимся в коде контроллера); в частности, в приведенном выше примере это означает, что если сообщение журнала создается, например, в конструкторе ARandomClass, это все равно имя менеджера ( в данном случае), которое должно отображаться.
  • Все исключения должны перехватываться и приводить к созданию «КРИТИЧЕСКОГО» сообщения журнала (также содержащего имя, как описано выше)
    В пользовательском приложении пользователю не нужно ничего делать, кроме одного оператора импорта и одного простого оператора для каждого журнала. Должны поддерживаться стандартные исключения (т. е. пользователям нельзя предлагать использовать только специальные исключения).
Единственный способ удовлетворить эти требования, который я нашел, — это использовать единый регистратор и инкапсулировать в коде контроллера все вызовы методов менеджера. Примерно так:

Код: Выделить всё

import logging

class MyLogger:
pass #some basic logic here using **a single logger** from logging module

class Controller:

def __init__(self,managerinfo):
self.logger = MyLogger()
self.managers = []
for mtyme,mname in managerinfo:
self.logger.setName(mname)
m = mtype(mname)
self.logger.setName(None)
self.managers.append(m)

def run(self):
# do something with managers, for instance:
self.logger.setName(self.managers[0].name)
self.managers[0].parseStuff()
self.logger.setName(self.managers[1].name)
self.managers[1].cleanStuff()
self.logger.setName(None)
Управление исключениями будет осуществляться путем переопределения sys.excepthook и использования того же регистратора.
Это работает, но не выглядит нравится стандартный способ использования модуля журналирования (один регистратор на модуль), и я не очень доволен архитектурой. На самом деле, с таким шаблоном практически нет необходимости использовать модуль журналирования (достаточно одного класса, инкапсулирующего print). Существует ли более стандартный/лучший способ достижения того, что я здесь описал?

Подробнее здесь: https://stackoverflow.com/questions/781 ... asy-interf

Вернуться в «Python»