Подтвердить что ты не робот

Python - отправлять электронную почту, когда исключается исключение?

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

Method1()

Method2()

...........

...........

MethodN()

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

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

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

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

4b9b3361

Ответ 1

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

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

if problem_test():
    SendEmail()
    raise Exception

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

def raise_email(self, e):
    SendEmail()
    raise e

Ответ 2

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

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

import logging
import logging.handlers

smtp_handler = logging.handlers.SMTPHandler(mailhost=("smtp.example.com", 25),
                                            fromaddr="[email protected]", 
                                            toaddrs="[email protected]",
                                            subject=u"AppName error!")


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

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

С уважением.

Ответ 3

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

Ответ 4

Остерегайтесь ученика мастера!

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

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

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

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

Ответ 5

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

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)

Ответ 6

Gist Link

Самый важный трюк здесь, если защищенный параметр не передан, значение по умолчанию Нет, которое вызывает исключение, если вы пытаетесь выполнить аутентификацию с помощью TLS/SSL enabled 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="[email protected]",
        toaddrs="[email protected]",
        subject="EXCEPTION",
        credentials=('[email protected]', 'MY SECRET PASSWORD'),
        secure=()))
    try:
        foo()
    except Exception, e:
        logging.exception(e)


if __name__ == '__main__':
    main()

Ответ 7

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

class MyException(Exception):
    def __init__(self):
        SendEmail()

Ответ 8

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

Ответ 9

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

см. sys.excepthook

Ответ 10

Вы можете использовать библиотеку предупреждений 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))

Ответ 11

Мне нравятся ответы, в которых используется модуль logging, но для этого я использую библиотеку smtp (smtplib). Чтобы отправить сообщение об ошибке, я делаю что-то вроде следующего в ветки исключений блока try/except:

import smtplib as smtp

s = smtplib.SMTP('smtp.gmail.com', 587)
s.starttls()  
from_user = r"[email protected]"
to_user = r"[email protected]"
password = "xxxxxxxx"  
s.login(from_user, password)
subject = "Uh oh"
text = "XYZ error message you blew it!"
message = f"Subject: {subject}\n\n{text}"
s.sendmail(from_user, to_user, message);

Это хорошо работает, но не самый безопасный вариант в мире. На самом деле вы должны сообщить Google, что хотите разрешить менее безопасным приложениям подключаться (вы можете изменить этот параметр здесь: https://myaccount.google.com/lesssecureapps).