【问题标题】:How to notify myself when a python script runs into an error or just stops?如何在 python 脚本遇到错误或停止时通知自己?
【发布时间】:2019-10-03 07:52:44
【问题描述】:

我有一个在 Ubuntu 上运行并处理 MySQL 数据库内容的 python 脚本。我想在脚本遇到未处理的exception 或完成处理时收到通知。

实现这一目标的适当方法是什么?

我曾想过使用this SO-Answer 中显示的方法从 python 中向自己发送一封电子邮件,但为了能够做到这一点,我必须对我的登录数据进行硬编码——我对此并不满意(脚本在公共服务器上运行公司内部)。

有什么建议可以绕过它或使用更合适的方式实现它?

【问题讨论】:

  • 此登录数据是用于验证您的 SMTP 服务器还是 MySQL 或两者?
  • 使用 SMTP 服务器。我想为此使用我的 GMail 帐户。

标签: python ubuntu notifications


【解决方案1】:

这很有魅力:https://www.quora.com/How-can-I-send-a-push-notification-to-my-Android-phone-with-a-Python-script

在 PC 上:安装通知我

pip install notify-run

然后注册为:notify-run register

现在在您的手机上扫描代码并允许来自该站点的通知。

然后你的脚本可以这样通知你:

from notify_run import Notify
notify = Notify()
notify.send('any message you want')

【讨论】:

    【解决方案2】:

    通过 SMTP 发送电子邮件时,您通常不需要提供登录数据。如果我是你,我会试验你链接到的答案中给出的代码,并在你公司的 SMTP 服务器上试用。

    【讨论】:

    • 您能否解释一下您所说的您...通过 SMTP 发送电子邮件时不需要提供登录数据。 ...?
    • @Aufwind:我的意思是,如果您向abc@xyz.com 发送电子邮件,并连接到xyz.com 的SMTP 服务器(即MX 记录中列出的服务器) ,在大多数情况下,它会接受您的电子邮件,而无需您提供任何登录详细信息。
    【解决方案3】:

    这是我编写的一个异常处理程序,并在脚本终止时使用它通过电子邮件发送异常。设置为sys.excepthook = ExceptHook:

    import os
    import sys
    import traceback
    import re
    import smtplib
    import getpass
    
    def ExceptHook(etype, value, tb):
        """Formats traceback and exception data and emails the error to me: &^&^@&^&^&.com.
    
        Arguments:
        etype -- Exception class type
        value -- Exception string value
        tb -- Traceback string data
        """
    
        excType = re.sub('(<(type|class \')|\'exceptions.|\'>|__main__.)', '', str(etype)).strip()
        Email = {'TO':"*****@*****.com", 'FROM':getpass.getuser() + '@blizzard.com', 'SUBJECT':'**  Exception **', 'BODY':'%s: %s\n\n' % (excType, etype.__doc__)}
    
        for line in traceback.extract_tb(tb):
            Email['BODY'] += '\tFile: "%s"\n\t\t%s %s: %s\n' % (line[0], line[2], line[1], line[3])
        while 1:
            if not tb.tb_next: break
            tb = tb.tb_next
        stack = []
        f = tb.tb_frame
        while f:
            stack.append(f)
            f = f.f_back
        stack.reverse()
        Email['BODY'] += '\nLocals by frame, innermost last:'
        for frame in stack:
            Email['BODY'] += '\nFrame %s in %s at line %s' % (frame.f_code.co_name, frame.f_code.co_filename, frame.f_lineno)
            for key, val in frame.f_locals.items():
                Email['BODY'] += '\n\t%20s = ' % key
                try:
                    Email['BODY'] += str(val)
                except:
                    Email['BODY'] += '<ERROR WHILE PRINTING VALUE>'
        thisHost = socket.gethostname()
        thisIP = socket.gethostbyname(thisHost)
        gmTime = time.gmtime()
        logName = 'SomeTool_v%s_%s_%s_%s.%s.%s_%s.%s.%s.log' % (__version__, thisHost, thisIP, gmTime.tm_mon, gmTime.tm_mday, gmTime.tm_year, gmTime.tm_hour, gmTime.tm_min, gmTime.tm_sec)
        if not os.path.exists(LOGS_DIR):
            try:
                os.mkdir(LOGS_DIR)
            except:
                baseLogDir = os.path.join(NET_DIR, "logs")
                if not os.path.exists(baseLogDir):
                    try:
                        os.mkdir(baseLogDir)
                    except:
                        pass
                    else:
                        open(os.path.join(baseLogDir, logName), 'w').write(Email['BODY'])
            else:
                open(os.path.join(LOGS_DIR, logName), 'w').write(Email['BODY'])
        Email['ALL'] = 'From: %s\nTo: %s\nSubject: %s\n\n%s' % (Email['FROM'], Email['TO'], Email['SUBJECT'], Email['BODY'])
        server = smtplib.SMTP(MY_SMTP)
        server.sendmail(Email['FROM'], Email['TO'], Email['ALL'])
        server.quit()
    
    if __name__ == '__main__':
        sys.excepthook = ExceptHook
        try:
            1 / 0
        except:
            sys.exit()
    

    【讨论】:

      【解决方案4】:

      如果您使用 cron 运行它,我建议您在 bash 中查看 Python 之外的脚本的返回值。例如,如果脚本引发异常,您将获得返回值 1:

      $ python test.py 
      Traceback (most recent call last):
        File "test.py", line 7, in <module>
          raise ValueError("test")
      ValueError: test
      $ echo $?
      1
      

      虽然干净的退出返回 0:

      $ python test.py 
      $ echo $?
      0
      

      要监控 cron,您可以将返回值写入某个文件中。然后,当文件包含 0 或 when the timestamp is older than how often your cron is supposed to run 以外的值时,使用 monit 通知您。

      【讨论】:

        【解决方案5】:

        那台机器是否安装了 sendmail,我只会使用 sendmail 发送电子邮件,而不是直接与 smtp 服务器对话,例如试试这个

        echo -e "To: auniyal@example.com\nSubject: Testx\nTest\n" | sudo sendmail -bm -t -v
        

        它将在详细模式下显示 sendmail 的运行情况,如果它有效,您可以使用 sendmail 发送电子邮件,例如

            ps = Popen(["/usr/lib/sendmail"]+list(your_recipents), \
                       stdin=PIPE)
            ps.stdin.write('you msg')
            ps.stdin.flush()
            ps.stdin.close()
        

        【讨论】:

          【解决方案6】:

          您的一些选择是 -

          如果您可以访问公司网络上的机器/服务器,您可以在其中设置一个简单的 SMTP 服务器作为邮件中继。然后,您可以在那里更安全地配置 GMail 的登录详细信息,具体取决于谁都可以访问该机器。它甚至可以作为一个简单的虚拟机在另一台服务器上运行。只有您有权访问的虚拟机。然后使用此服务器从您的 python 脚本发送邮件。

          如果您无法访问公司网络上的服务器,您可以寻找不需要身份验证的 SMTP 服务器。

          或者另一种选择是创建一个仅用于发送电子邮件和使用其凭据的 GMail 用户。

          【讨论】:

            【解决方案7】:

            您可以使用 GMail API。它不需要您在脚本中输入密码。 This answer 可能会有所帮助。

            【讨论】:

              猜你喜欢
              • 2011-05-27
              • 2015-09-01
              • 1970-01-01
              • 2021-10-19
              • 1970-01-01
              • 2011-09-19
              • 2022-06-15
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多