Python - 异常升级时发送电子邮件?

时间:2011-05-31 03:20:22

标签: python exception-handling

我有一个python类,有很多方法():

Method1()

Method2()

...........

...........

MethodN()

所有方法 - 在执行不同任务时 - 都采用相同的方案:

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

我希望每当在课堂上的任何地方引发异常时都能收到电子邮件。

有没有简单的方法将这个逻辑组合到类中,而不是在每个SendEmail()语句之前调用raise Exception?什么是正确的,pythonic方式处理这种情况? canh''generalized'异常处理程序是解决方案吗?我很高兴你有任何想法。

12 个答案:

答案 0 :(得分:58)

像@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')

问候。

答案 1 :(得分:8)

Python stdlib有专门的类来做你想要的。见logging.handlers.SMTPHandler

答案 2 :(得分:7)

注意:虽然这是一个简单明了的问题解决方案,但below answer在大多数情况下可能更好。

如果替代方案如下:

if problem_test():
    SendEmail()
    raise Exception

那么为什么不定义自定义raise_email方法?

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

答案 3 :(得分:5)

小心the wizard's apprentice

最好记录这些错误,然后检查上次发送电子邮件的时间,如果时间跨度太短,请不要发送另一条消息,因为人类已经在查看日志文件。对于很多事情来说,每天只发一条消息就足够了,但即使对于系统关键的事情,如果你已经有一次失败,如果你等了两个小时发送下一封电子邮件会出现什么问题?

如果您每两小时发送一封电子邮件,那么每天最多的电子邮件数量为12.如果您遇到级联故障(您会!)那么很可能会在第一次发送后的几个小时内发生失败事件。

大多数大型网络公司提供4小时的SLA来修复故障,从最初发生故障开始计算(因为级联故障往往会重复),直到客户满意为止。如果您的SLA比SLA更严格,那么除非是某些金融行业服务,否则您可能提供的服务水平太高。

但如果您确实有4小时的SLA,那么我会确保在最后一封电子邮件的2到4小时内发送的任何电子邮件应该使用任何花哨的功能来确定它的优先顺序,突出显示它等等。实例使用X-Priority标头并在主题中放置单词URGENT,以便您的邮件客户端可以用大红色粗体字母显示它。

答案 4 :(得分:3)

也许是这样的事情?

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)

答案 5 :(得分:3)

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()

答案 6 :(得分:2)

这个怎么样:

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

答案 7 :(得分:1)

到2019年,最简单,最好的选择似乎是sentry

您只需要两行代码:

import sentry_sdk
sentry_sdk.init("https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx@sentry.io/xxxxxxx")

,它将向您发送详细的电子邮件,其中包含任何出现的错误。

答案 8 :(得分:0)

我只是subclass Exception并在自定义例外中发送电子邮件。

答案 9 :(得分:0)

您可以使用except hook在未捕获异常时发送电子邮件。

请参阅sys.excepthook

答案 10 :(得分:0)

您可以使用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 :(得分:0)

我喜欢使用logging模块的答案,但是为此我使用了smtp库(smtplib)。要发送错误消息,我在try/except块的异常分支中执行以下操作:

import smtplib as smtp

s = smtplib.SMTP('smtp.gmail.com', 587)
s.starttls()  
from_user = r"foo@gmail.com"
to_user = r"bar@gmail.com"
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)。