Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling exception in python tkinter

Tags:

python

tkinter

I have written an application in Python Tkinter. I recently noticed that for one of the operation, it sometimes closes (without giving any error) if that operation failed. I have written a small program to illustrate the problem :-

import os
from Tkinter import *

def copydir():
    src = "D:\\a\\x\\y"
    dest = "D:\\a\\x\\z"
    os.rename(src,dest)

master = Tk()

def callback():
    global master
    master.after(1, callback)
    copydir()
    print "click!"

b = Button(master, text="OK", command=copydir)
b.pack()

master.after(100, callback)

mainloop()

To reproduce the problem, open the folder which it will rename in “ms command prompt” such that renaming it will throw exception from Tkinter code.

My original code is using threading and is performing other tasks as well, so I have tried to make the operations in this test script as similar as possible.

Now, if I run this code by double clicking it, then program simply closes without throwing any error. But If I had been running this script from console, then exception messages are dumped on the console and atleast I got to know , something is wrong.

I can fix this code by using try/catch in the code where it tried to rename but I want to inform user about this failure as well. So I just want to know what coding approaches should be followed while writing Tkinter App's and I want to know:-

1) Can I make my script dump some stack trace in a file whenever user ran this by double clicking on it. By this atleast, I would know something is wrong and fix it.

2) Can I prevent the tkinter app to exit on such error and throw any exception in some TK dialog.

Thanks for help!!

like image 476
sarbjit Avatar asked Mar 06 '13 11:03

sarbjit


People also ask

How do you handle exceptions in Python?

In Python, we catch exceptions and handle them using try and except code blocks. The try clause contains the code that can raise an exception, while the except clause contains the code lines that handle the exception.

What is exception handling in GUI?

Uncaught exceptions in GUI applications In practical terms, an exception to this is in GUI applications (including Swing applications), where an uncaught exceptions occurs in the event dispatch thread. This means in event handlers, such as the actionPerformed() method of an ActionListener.

What is Tk Tk () in Python?

Tkinter is a Python package which comes with many functions and methods that can be used to create an application. In order to create a tkinter application, we generally create an instance of tkinter frame, i.e., Tk(). It helps to display the root window and manages all the other components of the tkinter application.


1 Answers

I see you have a non-object oriented example, so I'll show two variants to solve the problem of exception-catching.

The key is in the in the tkinter\__init__.py file. One can see that there is a documented method report_callback_exception of Tk class. Here is its description:

report_callback_exception()

Report callback exception on sys.stderr.

Applications may want to override this internal function, and should when sys.stderr is None.

So as we see it it is supposed to override this method, lets do it!

Non-object oriented solution

import tkinter as tk
from tkinter.messagebox import showerror


if __name__ == '__main__':

    def bad():
        raise Exception("I'm Bad!")

    # any name as accepted but not signature
    def report_callback_exception(self, exc, val, tb):
        showerror("Error", message=str(val))

    tk.Tk.report_callback_exception = report_callback_exception
    # now method is overridden

    app = tk.Tk()
    tk.Button(master=app, text="bad", command=bad).pack()
    app.mainloop()

Object oriented solution

import tkinter as tk
from tkinter.messagebox import showerror


class Bad(tk.Tk):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # or tk.Tk.__init__(*args, **kwargs)

        def bad():
            raise Exception("I'm Bad!")
        tk.Button(self, text="bad", command=bad).pack()

    def report_callback_exception(self, exc, val, tb):
        showerror("Error", message=str(val))

if __name__ == '__main__':

    app = Bad()
    app.mainloop()

The result

My environment:

Python 3.5.1 |Anaconda 2.4.1 (64-bit)| (default, Dec  7 2015, 15:00:12) [MSC  
v.1900 64 bit (AMD64)] on win32

tkinter.TkVersion
8.6

tkinter.TclVersion
8.6
like image 92
Maxim Kochurov Avatar answered Sep 23 '22 23:09

Maxim Kochurov