Making Python Scripts Show Windows-friendly Errors/Stacktrace

2 min read · Posted on: Jun 20, 2007 · Print this page

Most of us love to distribute our python programs to others once you have finished coding a neat little script. For Windows users we package it using Py2exe or cx_freeze. However, many of the end-users will not be happy with a black command window popping up, say, when an error is thrown.

Of course the alternative is to write a full blown GUI application using WXPython or PyFLTK. Even the latter, though quite lightweight, adds several megabytes to the distribution, when all you need is a simple message-box indicating an error or showing some informational text. Clearly, its an overkill for your throwaway python scripts.

This is the kind of problem I typically face and I have found a good solution. The answer is ctypes library which comes as a part of the standard distribution from Python 2.5 onwards. It simply calls the messagebox function from user32.dll (which is always present in a windows installation). With the main problem solved, what remained was to obtain the error text and stack trace.

Let’s see how the code looks like:

# Importing all the works for a native Win32 Message Box
from ctypes import c_int, WINFUNCTYPE, windll
from ctypes.wintypes import HWND, LPCSTR, UINT
prototype = WINFUNCTYPE(c_int, HWND, LPCSTR, LPCSTR, UINT)
paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "caption", None), (1, "flags", 0)
MessageBox = prototype(("MessageBoxA", windll.user32), paramflags)
 # For printing the stack
import sys
import traceback
from time import sleep

def show_popup(text):
    print text
    MessageBox(text=text, caption="Sample App Says...")

def mainloop():
    raise "Uff!"

if __name__ == '__main__':
    try:
        mainloop()
    except:
        type, value, sys.last_traceback = sys.exc_info()
        lines = traceback.format_exception(type, value,sys.last_traceback)
        show_popup("Aiyooooo..... there has been an error!\n" +
            "Exception in user code:\n" +
            "".join(lines) +
            "===== Please mail a screenshot to arunvr@gmail.com ===="
            )
    finally:
        sleep(1) # show the console output for a second so that users can read it

EDIT: This is how it looks like in PyMail, one of my scripts-that-grew-into-an-app ;)

Screenshot of a Python Stacktrace in a Messagebox


Arun Ravindran profile pic

Arun Ravindran

Arun is the author of "Django Design Patterns and Best Practices". Works as a Product Manager at Google. Avid open source enthusiast. Keen on Python. Loves to help people learn technology. Find out more about Arun on the about page.

Don't miss any future posts!

Comments →

Next: ▶   Wedding Microsite is Up!

Prev: ◀   Yet Another Year To Rock Away*

Up: ▲   Blog

Featured Posts

Frequent Tags

banner ad for Django book

Comments

powered by Disqus