How to notify myself when a python script runs into an error or just stops?
I have a python script which runs on Ubuntu and processes the content of a MySQL Database. I want to be informed when the script开发者_如何转开发 runs into an unhandled exception
or when it is done processing.
What is the appropriate way to make this happen?
I thought of sending myself an email from within python using the method shown in this SO-Answer, but to be able to do that I have to hardcode my logindata - which I am not comfortable with (the script runs on a public server within the company).
Any suggestions to bypass that or to make it happen using a more appropriate way?
This worked as charm: https://www.quora.com/How-can-I-send-a-push-notification-to-my-Android-phone-with-a-Python-script
ON PC: install notify-me
pip install notify-run
then register it as: notify-run register
now on your mobile scan the code and allow notification from this site.
Then your script can notify you like this:
from notify_run import Notify
notify = Notify()
notify.send('any message you want')
You typically don't need to supply login data when sending an email over SMTP. If I were you, I'd experiment with the code given in the answer you've linked to and try it out with your company's SMTP server.
Here is an exception handler I wrote and use that emails the exception when the script dies. Set it with 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()
If you're running this with cron, I would suggest looking at the return value of the script outside of python in bash. For example, if the script raises an exception, you will get a return value of 1:
$ python test.py
Traceback (most recent call last):
File "test.py", line 7, in <module>
raise ValueError("test")
ValueError: test
$ echo $?
1
While a clean exit returns 0:
$ python test.py
$ echo $?
0
To monitor the cron, you can write the return value to a file somewhere. Then, use monit to notify you when the file contains a value other than 0, or when the timestamp is older than how often your cron is supposed to run.
Does that machine have sendmail installed, I would just use sendmail to send emails instead of directly talking to smtp server e.g. try this
echo -e "To: auniyal@example.com\nSubject: Testx\nTest\n" | sudo sendmail -bm -t -v
It will show sendmail in action in verbose mode and if it works you can just use sendmail to send email e.g.
ps = Popen(["/usr/lib/sendmail"]+list(your_recipents), \
stdin=PIPE)
ps.stdin.write('you msg')
ps.stdin.flush()
ps.stdin.close()
Some of your options are -
If you have access to a machine/server on the company network, where you can setup a simple SMTP server as a mail relay. You can then configure your login details for GMail a bit more securely there, depending on who all has access to the machine. It could potentially even be run as a simple VM on another server. A VM that only you have access to. Then use this server for sending mail from your python script.
If you don't have access to a server on the company network, you could look for SMTP servers which don't require authentication.
Or another option is to create a GMail user just for sending out emails and using its credentials.
You may use GMail API. It doesn't need your password inside the script. This answer might help.
精彩评论