Форум сайта python.su
0
Всем привет.
Написал огромный модуль (переписал с php - не мое на py).
Задано оч много Exception, сообщения которых всегда начинаются с некоторого шаблона.
Для примера:
class Server(object): """docstring for Server""" def __init__(self, id_): self.__id = id_ self.__ip = None @property def log_head(self): return "Server ID: {} IP: {}. ".format(self.id, self.ip) @property def ip(self): return self.__ip @property def id(self): return self.__id def test(self): raise SrvException("{}We have some problem.".format(self.log_head))
class SrvException(Exception): _target_srv = None class __metaclass__(type): @property def target_srv(cls): return cls._target_srv @target_srv.setter def target_srv(cls, srv_inst): cls._target_srv = srv_inst def __init__(self, message): ip = SrvException.target_srv.ip id_ = SrvException.target_srv.id message = "Server ID: {} IP: {}. {}".format(id_, ip, message) super(SrvException, self).__init__(message) class Server(object): """docstring for Server""" def __init__(self, id_): SrvException.target_srv = self self.__id = id_ self.__ip = None @property def ip(self): return self.__ip @property def id(self): return self.__id def test(self): raise SrvException("We have some problem.") inst = Server(0) inst.test()
SrvException.target_srv = self
Отредактировано Dezex (Май 6, 2019 21:45:55)
Офлайн
568
Dezex
Мне кажется, в ваших размышлениях есть концептуальная ошибка. Исключения и логгирование исключений, это совершенно разные и непересекающиеся аспекты программы. Исключения возникают потому, что в программе произошли непредвиденные события, программа сообщает о неполадках. Логгирование ошибок - один из инструментов администрирования, его наличие или отсутствие никак не влияет на то, что в программе возникают исключительные ситуации, не надо искусственно связывать эти задачи.
import logging logging.basicConfig(filename="sample.log", level=logging.INFO) class Logger: def __init__(self, server): self.server = server def text(text): return f"[{self.server.ip}-{self.server.id}] {text}" def debug(text): logging.debug(selt.text(text)) def error(text): logging.error(self.text(text)) class Server: def __init__(self): self.logger = Logger(self) def test(self): try: connect() except ConnectionError as e: self.logger.error(e)
Офлайн
0
FishHook
Спасибо за ответ. И за наводку на библиотеку logging - не пользовался (самопал), удобно.
Да, я представляю разницу в исключениях и логировании.
И изначально я переделывал Excpetion (которые пред. автор использовал в PHP) на логирование (для начала самопальная функция в том же классе), но понял вот что:
набор пакетов, модулей немалый (проект), некоторые вещи я могу упустить (ошибки в коде, которые вызовут эти самые предполагаемые Exception). И мне удобнее получить место в модуле, коде, что и дает raise Exception в одну строчку. Поэтому логи типа error, debug должны поднимать эту информацию.
Посмотрел на logging, было бы мощно, если она могла делать так:
при необходимости (через аргументы basicConfig) можно включать трассировку на местах .error, .debbug сообщений дополнительно к стд. тексту.
Офлайн
568
Dezex
можно включать трассировку на местах
import logging logging.basicConfig(level=logging.DEBUG) try: 1 / 0 except Exception: logging.exception("AHTUNG!!!!!") logging.debug("The program successfully completed")
Офлайн
0
FishHook
Так фишка в том, что не та логика: я не использую try/except.
Проверка идет по условию, например переменная установлена или нет.
И опять спасибо за logging. В принципе получилось то, что я хотел: сообщение + вкл/выкл трассировка по коду по уровню DEBUG. Но немного криво - поднимаю Exception рядом с логером.
Пример:
import sys import logging logging.basicConfig(level=logging.DEBUG, format="%(levelname)-0s:%(name)-0s: %(message)s") class Logger: def __init__(self, server): self.server = server self.logger = logging.getLogger() def text(self, text): return "Server ID: {}, IP: {}. {}".format(self.server.id, self.server.id, text) def debug(self, text): self.logger.debug(self.text(text)) def error(self, text): self.logger.error(self.text(text)) def critical(self, text): self.logger.critical(self.text(text)) if self.logger.isEnabledFor(logging.DEBUG): print "" raise Exception sys.exit() class Server: def __init__(self, id_): self.logger = Logger(self) self.__id = id_ self.__ip = None @property def ip(self): return self.__ip @property def id(self): return self.__id def test(self): var = None if var is None: self.logger.critical("Variable value was not setted.") inst = Server(0) inst.test() sys.exit()
CRITICAL:root: Server ID: 0, IP: 0. Variable value was not setted. Traceback (most recent call last): File "./__debug.py", line 105, in <module> inst.test() File "./__debug.py", line 101, in test self.logger.critical("Variable value was not setted.") File "./__debug.py", line 78, in critical raise Exception Exception
Отредактировано Dezex (Май 7, 2019 13:17:51)
Офлайн
568
Dezex
Я думаю так: если программа не может дальше работать с имеющимися данными, например, не до конца проиницировали переменную билдером, то это исключительная ситуация, и эксепшен должен быть зарайзен. Если какой-то внешний по отношению к сущности, в которой возникла ошибка, перехватит этот эксепшен - ну отлично, видимо, он знает, что делает.
class Server: def test(self): var = None if var is None: raise ServerError("var is undefined") inst = Server(0) try: inst.test() except ServerError as e: logger.error(e)
Офлайн
0
FishHook
Да, у меня в итоге так и получается, но неявно через self.logger.critical. Я затеял это из-за доп. информации, которая повторяется:
CRITICAL:root: Server ID: 0, IP: 0. Variable value was not setted.
+ единый интерфейс - Logger
Отредактировано Dezex (Май 7, 2019 13:38:09)
Офлайн
186
> Задано оч много Exception, сообщения которых всегда начинаются с некоторого шаблона….
> Хочу убрать (спрятать) self.log_head, чтобы не указывать каждый раз.
> Додумался ток до этого:
Ты до какой-то ерунды додумался. Используй наследование и всё будет хорошо.
Офлайн
0
Rodegast
А пример?
Офлайн
186
> А пример?
Какой пример? Про наследование?
class SrvException(Exception): @property def log_head(self): return "Server ID: {} IP: {}. ".format(self.id, self.ip) class ServerException(SrvException): def __init__(self, _id, ip=None): self.__id = _id self.__ip = ip @property def ip(self): return self.__ip @property def id(self): return self.__id
Офлайн