Python - отправлять электронную почту, когда исключается исключение?
У меня есть класс python
со многими методами():
Method1()
Method2()
...........
...........
MethodN()
Все методы - при выполнении разных задач - имеют одну и ту же схему:
do something
do something else
has anything gone wrong?
raise an exception
Я хочу получать электронную почту всякий раз, когда исключение возникает где-либо в классе.
Есть ли простой способ объединить эту логику в класс, а не вызывать SendEmail()
перед каждым оператором raise Exception
? Каков правильный, питонический способ справиться с таким делом? canh "обобщенный" обработчик исключений - это решение? Я был бы рад за любые идеи, которые у вас могут быть.
Ответы
Ответ 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).