Making Python Scripts Show Windows-friendly Errors/Stacktrace

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

Comments

blog comments powered by Disqus

Go back to top