# Author: Miguel Martinez Lopez # # Uncomment the next line to see my email # print("Author's email: %s"%"61706c69636163696f6e616d656469646140676d61696c2e636f6d".decode("hex")) """ I provide in this module the function "exec_async". "exec_async" executes the function "computation" asyncronously with the provided "args" and "kwargs". If "callback" is provided, it will be called with the result when the computation is finnished. "Polling" will be the frequency to poll to check for results. There is two methods to execute the task: using multiprocessing or using threads. """ import traceback MULTIPROCESSING = 0 THREADS = 1 def exec_async(window, computation, args=(), kwargs={}, callback=None, polling=100, method=MULTIPROCESSING): if method == MULTIPROCESSING: _request_results = _request_results_using_multiprocessing elif method == THREADS: _request_results = _request_results_using_threads future_result = _request_results(computation, args=args, kwargs=kwargs) if callback: _after_completion(window, future_result, callback, polling) return future_result def _request_results_using_multiprocessing(func, args, kwargs): import multiprocessing future_result= multiprocessing.Queue() request_parameters = func, args, kwargs, future_result worker = multiprocessing.Process(target=_compute_result, args=request_parameters) worker.daemon = True worker.start() return future_result def _request_results_using_threads(func, args, kwargs): import threading import Queue future_result= Queue.Queue() request_parameters = func, args, kwargs, future_result worker = threading.Thread(target=_compute_result, args=request_parameters) worker.daemon = True worker.start() return future_result def _after_completion(window, future_result, callback, polling): def check(): try: result = future_result.get(block=False) except: window.after(polling, check) else: callback(result) window.after(0, check) def _compute_result(func, func_args, func_kwargs, future_result): try: _result = func(*func_args, **func_kwargs) except Exception as errmsg: _result = Exception(traceback.format_exc()) future_result.put(_result) if __name__ == "__main__": try: from Tkinter import Tk, Frame, Entry, Label, Button, IntVar, StringVar, LEFT import tkMessageBox as messagebox except ImportError: from tkinter import Tk, Frame, Entry, Label, Button, IntVar, StringVar, LEFT from tkinter import messagebox def fibonnacci(n): if n == 0: return 0 elif n == 1: return 1 else: return fibonnacci(n-1)+fibonnacci(n-2) disabled = False def calculate_fibonacci(): global disabled if disabled: messagebox.showinfo("warning", "It's still calculating...") return def callback(result): global disabled disabled = False result_var.set(result) disabled = True exec_async(root, fibonnacci, args=(n.get(),), callback=callback) root = Tk() n = IntVar(value=1) row = Frame(root) row.pack() Entry(row, textvariable=n).pack(side=LEFT) Button(row, text="Calculate fibonnaci", command =calculate_fibonacci).pack(side=LEFT) Button(row, text="It's responsive", command= lambda: messagebox.showinfo("info", "it's responsive")).pack(side=LEFT) result_var = StringVar() Label(root, textvariable=result_var).pack() root.mainloop()