Python - отправлять электронную почту при возникновении исключения? - PullRequest
12 голосов
/ 31 мая 2011

У меня есть класс python со многими методами ():

Method1()

Method2()

...........

...........

MethodN()

Все методы - при выполнении разных задач - имеют одинаковую схему:

do something
do something else
has anything gone wrong?
    raise an exception

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

Есть ли какой-нибудь простой способ объединить эту логику в классе, а незвонить SendEmail() перед каждым raise Exception оператором?какой правильный, питонный способ справиться с таким случаем?Может ли «обобщенный» обработчик исключений быть решением?Буду рад любым вашим идеям.

Ответы [ 10 ]

60 голосов
/ 31 мая 2011

, как @User сказал, прежде чем Python имеет logging.handlers.SMTPHandler для отправки зарегистрированного сообщения об ошибке. Используйте модуль регистрации! Переопределение класса исключения для отправки электронного письма - плохая идея.

Быстрый пример:

import logging
import logging.handlers

smtp_handler = logging.handlers.SMTPHandler(mailhost=("smtp.example.com", 25),
                                            fromaddr="from@example.com", 
                                            toaddrs="to@example.com",
                                            subject=u"AppName error!")


logger = logging.getLogger()
logger.addHandler(smtp_handler)

try:
  break
except Exception as e:
  logger.exception('Unhandled Exception')

Привет.

8 голосов
/ 31 мая 2011

Python stdlib имеет специальный класс, чтобы делать то, что вы хотите. Смотри logging.handlers.SMTPHandler

7 голосов
/ 31 мая 2011

Примечание. Хотя это простое и очевидное решение проблемы, как указано, ответ ниже , вероятно, лучше в большинстве случаев.

Если альтернатива такова:

if problem_test():
    SendEmail()
    raise Exception

Тогда почему бы вам просто не определить собственный raise_email метод?

def raise_email(self, e):
    SendEmail()
    raise e
5 голосов
/ 31 мая 2011

Осторожно ученик волшебника !

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

Если вы отправляете одно электронное письмо за двухчасовой промежуток времени, то максимальное количество электронных писем в день составляет 12. И если вы получаете каскадный сбой (у вас получится!), То, скорее всего, это произойдет в течение пары часов после первого событие сбоя.

Большинство крупных сетевых компаний предлагают SLA на 4 часа для устранения неисправности, измеряемой с момента его возникновения (потому что каскадные сбои имеют тенденцию повторяться) до тех пор, пока клиент не будет удовлетворен тем, что оно устранено. Если у вас более узкий SLA, чем этот, то, если это не какой-то сервис финансовой индустрии, вы, вероятно, предлагаете слишком высокий уровень обслуживания.

Но если у вас есть 4-часовой SLA, то я бы позаботился о том, чтобы любое электронное письмо, отправленное в течение 2–4 часов с момента последнего электронного письма, использовало все, что вам нужно, чтобы расставить приоритеты, выделить его и т. Д. Для Например, используйте заголовок X-Priority и поместите слово URGENT в тему, чтобы ваш почтовый клиент мог отображать его большими жирными красными буквами.

3 голосов
/ 11 декабря 2015

Gist Link

Самый важный трюк здесь, если безопасный параметр не передан, значением по умолчанию является Нет , что вызывает исключениеесли вы пытаетесь пройти проверку подлинности с помощью TLS/SSL серверов STMP, таких как серверы Gmail, Yahoo, Yandex, STMP.

Мы передали пустой кортеж для запуска smtp.ehlo() для правильной проверки подлинности с использованием SSL.

...
if self.secure is not None:
    smtp.ehlo()
    smtp.starttls(*self.secure)
    smtp.ehlo()
...


import logging
import logging.handlers

__author__ = 'Ahmed Şeref GÜNEYSU'


def foo():
    raise Exception("Foo Bar")


def main():
    logger = logging.getLogger()
    logger.addHandler(logging.handlers.SMTPHandler(
        mailhost=("smtp.mail.yahoo.com", 587),
        fromaddr="boss@example.com",
        toaddrs="me@example.com",
        subject="EXCEPTION",
        credentials=('smtpuser@example.com', 'MY SECRET PASSWORD'),
        secure=()))
    try:
        foo()
    except Exception, e:
        logging.exception(e)


if __name__ == '__main__':
    main()
3 голосов
/ 31 мая 2011

Что-то вроде этого, возможно?

def mailexception(ex):
  # Be creative.
  print 'Mailing... NOW!'

def pokemontrainer(cls):
  class Rye(cls):
    def __getattribute__(self, name):
      def catcher(func):
        def caller(*args, **kwargs):
          try:
            func(*args, **kwargs)
          except Exception, e:
            mailexception(e)
            raise
        return caller
      ref = cls.__getattribute__(self, name)
      if hasattr(cls, name) and hasattr(getattr(cls, name), '__call__'):
        return catcher(ref)
  return Rye

@pokemontrainer
class Exceptor(object):
  def toss(self, e):
    raise e('Incoming salad!')

ex = Exceptor()
ex.toss(ValueError)
2 голосов
/ 31 мая 2011

Как насчет этого:

class MyException(Exception):
    def __init__(self):
        SendEmail()
0 голосов
/ 14 июля 2019

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

https://github.com/sinarezaei/alerting

Пример кода:

from alerting import Alerting
from alerting.clients import AlertingMailGunClient, AlertingSlackClient, AlertingTelegramClient

alerts = Alerting(
  clients=[
    AlertingMailGunClient(your_mailgun_api_key, your_domain, from_email, target_email),
    AlertingSlackClient(your_bot_user_oauth, target_channel),
    AlertingTelegramClient(bot_token, chat_id)
  ]
)


try:
  # something
except Exception as ex:
  alerting.send_alert(title='some bad error happened', message=str(ex))

0 голосов
/ 31 мая 2011

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

см. sys.excepthook

0 голосов
/ 31 мая 2011

Я бы просто подкласс Exception и отправил электронное письмо в пользовательском исключении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...