Welcome, guest | Sign In | My Account | Store | Cart

Even production applications have bugs, and it would be nice to have Python tracebacks emailed to you rather than dumped to the hapless user's screen. This recipe shows you how.

Python, 68 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# ---------------------------------------------------------------
def createMail(sender, recipient, subject, html, text):
    '''
    A slightly modified version of Recipe #67083, included here 
    for completeness
    '''
    import MimeWriter, mimetools, cStringIO
    out = cStringIO.StringIO()
    htmlin = cStringIO.StringIO(html)
    txtin = cStringIO.StringIO(text)

    writer = MimeWriter.MimeWriter(out)
    writer.addheader("From", sender)
    writer.addheader("To", recipient)
    writer.addheader("Subject", subject)
    writer.addheader("MIME-Version", "1.0")
    writer.startmultipartbody("alternative")
    writer.flushheaders()

    subpart = writer.nextpart()
    subpart.addheader("Content-Transfer-Encoding", "quoted-printable")
    pout = subpart.startbody("text/plain", [("charset", 'us-ascii')])
    mimetools.encode(txtin, pout, 'quoted-printable')
    txtin.close()

    subpart = writer.nextpart()
    subpart.addheader("Content-Transfer-Encoding", "quoted-printable")

    pout = subpart.startbody("text/html", [("charset", 'us-ascii')])
    mimetools.encode(htmlin, pout, 'quoted-printable')
    htmlin.close()
    writer.lastpart()
    msg = out.getvalue()
    out.close()
    return msg

# ---------------------------------------------------------------
def sendMail(sender, recipient, subject, html, text):
    import smtplib
    message = createMail(sender, recipient, subject, html, text)
    server = smtplib.SMTP("localhost")
    server.sendmail(sender, recipient, message)
    server.quit()

# ---------------------------------------------------------------
def main():
    '''
    the main body of your program
    '''
    print x # will raise an exception


# ---------------------------------------------------------------
if __name__ == '__main__':
    try:
        main()
    except:
        import sys, cgitb
        sendMail('bugs@yourdomain.com',
                'webmaster@yourdomain.com',
                'Error on yourdomain.com',
                cgitb.html(sys.exc_info()),
                cgitb.text(sys.exc_info()))

        # handle the error gracefully, perhaps doing a
        # http redirect if this is a cgi application or
        # otherwise letting the user know something happened
        # but that, hey, you are all over it

To make things just that much nicer, we utilize the cgitb module for html-formatting our traceback (with a plain-text version added for the times we are using a mail client that doesn't display html).

2 comments

Gustav Beck 18 years, 6 months ago  # | flag

Title. 5 stars for the lovely title, sadly none left...

Jesse Noller 18 years, 6 months ago  # | flag

Very Nice. Very nice. I dropped it into a program I have and added a bunch of random places to throw exceptions - everything works beautifully.