i have made a tkinter application on which i have a submit button, when i press this button a crawl request goes to request.get(url) method and it starts with the crawling and the tkinter becomes inactive untill it gives me the response. but i want another button "stop" in tkinter app which when pressed stops the process going in the background and next time i want i can press the submit button to again start the process.
i have tried destroy and quit methods available in tkinter but they closes the tkinter widget itself.
my code is :-
#!/usr/bin/python
# -*- coding: latin-1 -*-
from Tkinter import *
import thread
from tool_crawler import *
import tkMessageBox
import ttk
# function which accepts url from GUI and pass it further for the
def crawl(url):
time_delay = time_delay_box.get()
if url == "Please enter URL.......":
tkMessageBox.showerror("Error(错误)", "Please enter a valid URL(请输入有效网址)")
elif not url:
tkMessageBox.showerror("Error(错误)", "Please enter a valid URL(请输入有效网址)")
else:
tree.heading("#0", text=url)
links = find_links(url, time_delay)
#print links
for i, link in enumerate(links):
tree.insert("", i, str(i), text=link)
tree.bind("<Double-1>", OnDoubleClick)
# function will invoke when any node in tree is double clicked
def OnDoubleClick(event):
item = tree.identify('item',event.x,event.y)
url = tree.item(item,"text")
index = tree.index(item)
parent = tree.parent(item)
crawl_child(url,index,parent)
def crawl_child(url,index,parent):
links = find_links(url, time_delay)
#print links
for i, link in enumerate(links):
if not parent:
tree.insert(str(index), i, str(index)+"."+str(i), text=link)
else:
tree.insert(str(parent)+"."+str(index), i, str(parent)+"."+str(index)+"."+str(i), text=link)
# tkinter object
top = Tk()
top.configure(background='Lavender')
# window title
top.title("Fan Wan Crawler ")
# tkinter minimum and maximum size
top.minsize(width=1460, height=800)
top.maxsize(width=1460, height=800)
# url entry area i.e. text box to enter the URLS
url = Entry(top, bd =3, width = 180)
url.insert(0, "Please enter URL.......")
url.pack(side = TOP)
# function to show and hide the text on entry and exit
def default(event):
current = url.get()
if current == "Please enter URL.......":
url.delete ("0", END)
elif not current:
url.insert("0", "Please enter URL.......")
# code to call function default on focusin and focusout
url.bind("<FocusIn>", default)
url.bind("<FocusOut>", default)
# submit button which is performing action on submit
submit = Button(top, text="Submit(提交)", width=15, bg='lightblue', command=lambda: crawl(url.get()))
submit.pack(side = TOP)
# time delay label
time_label = Label(top, text="Time Dealy (时间延迟):", font= ("Helvetica", 12), bg="Lavender", fg = "green")
time_label.place(x=2, y=27)
# time delay Entry
time_delay_box = Spinbox(top, from_=0, to=100, width=3)
time_delay_box.place(x=175, y=27)
# time description
time_label = Label(top, text="(in sec.(以秒为单位))", font=("Helvetica", 12), bg="Lavender", fg = "green")
time_label.place(x=220, y=27)
# tree area
tree = ttk.Treeview(top, selectmode="browse", height= "36")
columns = tree.column("#0", minwidth=0, width=720, stretch=True)
tree.place(x=2,y=56)
top.mainloop()
basically i am calling find_links function which is present in sepearte file and have the function request.get to crawl the links, presently i am not using threads.So, is there any way to stop this process without using threads. i dont want to pause it i just want to kill this process.
You can use a thread to start the scraping / crawling in another thread and then create a pause / resume button that enables "pausing" and "unpausing" the spawned threads through the thread methods threading.Condition and threading.Lock()
Example of one way to set the threads up, didn't create the gui or anything just showed an example of how to use a pauseable thread with a button click in your GUI since how you choose to setup / incorporate the threads will differ. This assumes pausing and resuming will occur after the thread is finished processing the current request.get call. Trying to stop a thread dead middle of a task is an entirely different issue unto itself.
import threading, requests
import tkinter as tk
def switch_thread_states(widget):
#or whatever pause / resume text you wish for the widget / button
if widget['text'] == 'Pause'
widget['text'] = 'Resume'
else:
widget['text'] = 'Pause'
for thread in threading.enumerate():
if not isinstance(thread, threading._MainThread):
if thread.paused:
thread.resume()
else:
thread.pause()
class PauseableThread(threading.Thread):
def __init__(self, urls):
threading.Thread.__init__(self)
self.urls = urls
self.paused = False
self.pause_cond = threading.Condition(threading.Lock())
def run(self):
for url in self.urls:
with self.pause_cond:
while self.paused:
self.pause_cond.wait()
#make requests here or whatever you're doing
requests.get(url, headers={'User-Agent':'Mozilla/5.0 .....'})
def pause(self):
self.paused = True
self.pause_cond.acquire()
def resume(self):
self.paused = False
self.pause_cond.notify()
self.pause_cond.release()
#make root
#make a button that calls switch_thread_states on press
#spawn threads with urls lists etc
Related
I just made a simple project with Tkinter GUI, but when I launch it and enter username, its window stops responding 'til the requests and instaloader processes are done, then it will be ok. Can I make a 'please wait' thing to avoid not responding? or does it get better if I migrate to another GUI?
from tkinter import *
import instaloader
from PIL import ImageTk, Image
import requests
from io import BytesIO
def insta(username):
L = instaloader.Instaloader()
profile = instaloader.Profile.from_username(L.context, username)
label2.config(text=profile.full_name)
label3.config(text=profile.biography)
url=profile.get_profile_pic_url()
response = requests.get(url)
img_data = response.content
img = ImageTk.PhotoImage(Image.open(BytesIO(img_data)))
panel = Label(image=img)
panel.place(x=150,y=100)
label4.config(text="Done")
window = Tk()
window.geometry("600x600")
window.maxsize(600, 600)
window.minsize(600, 600)
window.title("Instagram Profile Downloader")
# label
label = Label(window, text="Enter UserName to Download Profile Image:",
fg="black", bg="#f4b265")
label.place(x=180, y=20)
label2 = Label(window, text="")
label2.place(x=100, y=70)
label3 = Label(window, text="")
label3.place(x=100, y=100)
label4 = Label(window, text="", fg="red")
label4.place(x=380, y=50)
# button
def butt():
if input.get() == "":
label4.config(text="Please Enter Username")
return
else:
insta(input.get())
button = Button(window, text="Download", fg="white",
bg="#095e95", command=butt)
button.place(x=310, y=47)
# input
input = Entry(window)
input.place(x=180, y=50)
window.mainloop()
Tkinter stuff is running in the main thread and so when you call something in the main thread that takes time the GUI will be blocked while that function is running. To solve this you need to use threads to make sure the call to insta is running separate from the main thread where tkinter is running but also need to make sure that you dont call tkinter functions on that other thread because tkinter only works in the main thread.
Here's an exemple of how you could acheive it:
import threading
class InstaThread:
def __init__(self, username):
self.profile = None
self.img_data = None
# Disable the button while instaloader is running
button["text"] = "Loading..."
button["state"] = DISABLED
self.thread = threading.Thread(target=self.insta, args=(username,))
self.thread.start()
self.check_thread()
# Check periodically if the function has alread run
def check_thread(self):
if self.thread.is_alive():
window.after(100, self.check_thread)
else:
label2.config(text=self.profile.full_name)
label3.config(text=self.profile.biography)
panel = Label(window)
img = ImageTk.PhotoImage(Image.open(BytesIO(self.img_data)))
# Also updated this so that the image would really show in the panel
panel.image = img
panel.config(image = img)
panel.place(x=150,y=100)
label4.config(text="Done")
# Reset button
button["text"] = "Download"
button["state"] = NORMAL
# Function that will be running in other thread and updating the profile and img_data varibles of this class
def insta(self, username):
L = instaloader.Instaloader()
self.profile = instaloader.Profile.from_username(L.context, username)
url=self.profile.get_profile_pic_url()
response = requests.get(url)
self.img_data = response.content
Now in the Butt function you just need to call InstaThread(input.get()) instead of insta(input.get()) and like this when you click the button it will disable and say Loading while the function is running and the rest of the GUI will continue working fine
Another suggestion I have is for you to make a class for your GUI so that you have it all in one place and can access it anywhere inside the class so that you dont have to be having global variables for buttons and labels.
I'm trying to run a multi thread application,
each thread is asking for the user to provide a string input after some tasks the thread does.
simpledialog.askstring(title, content, parent=window)
the problem is that you cannot use the main thread window as the parent window inside a thread because you'll end up with this error:
_tkinter.TclError: window ".!_querystring2" was deleted before its visibility changed
which is logical because the thread and the main thread are not synchronized
after hard research I've ended up with a solution which says
"Create a new TK window instance for the thread"
newWin = tk.Tk()
newWin.withdraw() #to make it invisible
simpledialog.askstring(title, content, parent=newWin)
newWin.destroy()
which will work for my case if I wouldn't have a main tk window instance inside the main thread.
the destroy method for the "newWin" is causing my main window to be destroyed as well.
and I'll be ended up with this error :
Tcl_AsyncDelete: async handler deleted by the wrong thread
tkinter isn't a thread safe, and not gives an easy life when using it cross threads.
does anyone have any idea/trick how can I ask a string from a user inside a thread?
Some extra info about my code :
I'm triggering this function by a button click:
#tree is a treeview widget
def click(tree):
threads = simpledialog.askstring("Threads", "How many threads?")
if threads is not None:
try:
threads = int(threads)
if threads > 0:
thread = tm.threadObject(name="checkAccounts", target=checkUsers, args=[tree, threads])
thread.start()
#instance passes automatically from the tm.threadObject
def checkUsers(instance, tree, threads):
for child in tree.get_children():
while len(tm.threadsManager.getThreads("checkAccountWorker")) >= threads and instance.alive:
print("Sleeping")
time.sleep(1)
if not instance.alive:
break
item = tree.item(child)
taskHandler = task.taskHandler(tree, child)
thread = tm.threadObject(name="checkAccountWorker", target=taskHandler.doAction, args=[taskHandler.CHECK_USER], kill=taskHandler.kill, killargs=[], passInstance = False)
thread.start()
#part of the doAction code:
def doAction(*args):
#some code behind
newWin = tkinter.Tk()
newWin.withdraw()
code = tkinter.simpledialog.askstring("Activation", "Enter recevied code : ", parent=newWin)
newWin.destroy()
self.currentStatus = "Entering code"
mainEvents.updateTreeItem(tree, "status", item, self.currentStatus)
def updateTreeItem(tree, column, item, value):
key = ""
for col in tree["columns"]:
if tree.heading(col)["text"].lower() == column.lower():
key = col
if key == "":
return
tree.set(item, key, value)
It works at the first attempt. but when I click again on the checkUsers button I end up with the error :
"Tcl_AsyncDelete: async handler deleted by the wrong thread"
I honestly don't know why
Every time button is clicked we create new threading.Thread object and start it. It's target will be the askString function.
In the askString we create new window and add to it widget simpledialog.askstring.
This code below will do the trick:
import tkinter as tk
from tkinter import simpledialog
import threading
def askString():
new_window = tk.Tk()
new_window.withdraw()
print(simpledialog.askstring(title = "String input", prompt = "What's your Name?:", parent = new_window))
new_window.destroy()
root = tk.Tk()
btn = tk.Button(root, text = "Click me!", command = lambda: threading.Thread(target = askString).start())
btn.pack()
root.mainloop()
How you get the value from the function to your GUI is up to your
implementation (framework).
Okay,
After some work around I've created my own "getString" window dialog..
code:
#staticmethod
def getString(title, content):
topLevel = tk.Toplevel()
topLevel.title(title)
topLevel.resizable(False, False)
strVar = tk.StringVar()
label = tk.Label(topLevel, text=content)
label.grid(column=0, row=0, columnspan=2)
entry = tk.Entry(topLevel, textvariable=strVar)
entry.grid(column=0, row=1)
def close(topLevel):
if entry.get() != "":
topLevel.destroy()
button = tk.Button(topLevel, text="Set", command=lambda: close(topLevel))
button.grid(column=1, row=1)
topLevel.lift()
while(topLevel.winfo_exists()): # wait until topLevel destroyed
time.sleep(1)
return strVar.get()
It's a bit messy.. couldn't manage to accomplish a cleaner solution but it works.
You can ask for a string inside a thread this way :)
If someone have a nicer way to do so you may suggest.
I have three widgets (shown below) - a label, an entry, and a button.
I'm hoping to accept user input of an integer when the button is clicked.
I get the following error: ERROR RESOLVED!
I was making this too complicated. Success is Mine!!!
I believe that my problem is related to this:
Stack Overflow Post on get()
I chopped it down to the minimum amount of code possible to achieve this before posting.
Any Ideas or obvious failures you see would be greatly appreciated.
Screenshot of screen #1 (should eventually progress to screen #2 after all the players are entered. Screen #2 is where the game will begin.):
Working Code:
from tkinter import *
import tkinter
from PIL import Image, ImageTk
# The next 2 imports override the basic Tk widgets
# widget options that use fg and bg will no longer work.
# Must use, instead, ttk.Style class
from tkinter import ttk
from tkinter.ttk import *
# See docs.python.org/8/library/tkinter.ttk.html
# Class Based Windows
# youtube.com/watch?v=RkaekNkIKNY
# Tkinter - GUI Eaxample Multiple Display Frames
# youtube.com/watch?v=KdoOm3xo8X0
def main():
root = tkinter.Tk()
window1 = Window(root, "Play_a_game_of_Pig", "969x690", "someMessage",
"pig.ico", 0)
return None
class Window:
number_of_players = 0
# int player_names[] = new player_names[number_of_players]
def __init__(self, root, title, geometry, message, iconbitmap,
playerNumber):
self.root = root # this is the instance variable for the entire window
self.root.title(title)
self.root.geometry(geometry)
self.root.iconbitmap(iconbitmap)
self.number_of_players = playerNumber
# Make the window show up in center of screen and not be ccovered up by anything else.
# self.root.eval('tk::PlaceWindow %s center' % self.root.wininfo_toplevel())
# this is an important line.
# self.root.mainloop()
def addPlayers():
"""Allows user to input the number of and names of all game players"""
# stackoverflow.com/questions/12169258/should-i-use-entrys-get-or-its-textvariables-for-tkinter-in-python
print("\n initial # of players = " + str(self.number_of_players))
# Collects user input from the entry and turns it into an int
# user_input_number_of_players.set(int(str(entry_player_number.get("1.0", 'end-1c'))))
try:
user_input_number_of_players = int(entry_player_number.get())
print("Inside try block, user_input = ")
print(user_input_number_of_players)
self.number_of_players = user_input_number_of_players
except ValueError:
tkinter.messagebox.showerror('Non-Integer Input', 'User MUST enter a player # greater than 1.', icon = 'error')
# tkinter.messagebox.deiconify()
# tkinter.messagebox.quit()
# tkinter.messagebox.destroy()
#user_input_number_of_players.set(int(str(entry_player_number.get("1.0", 'end-1c'))))
# Set class instance value to this input from the user
# self.number_of_players = user_input_number_of_players
print("# of players after click = " + str(self.number_of_players))
return self.number_of_players
print("# of players after click = " + str(self.number_of_players))
# Add a label
myLabel1 = tkinter.Label(self.root, text="Please Enter # of Players",
width=25)
myLabel1.config(font="Courier 14 bold")
myLabel1.grid(row=2, column=1)
# bind user input to a variable from the entry box.
# Specifies a name whose value is linked to the widget value.
user_input_number_of_players = tkinter.StringVar()
# add an entry box
entry_player_number = tkinter.Entry(self.root, width=5, borderwidth=5,
textvariable=user_input_number_of_players)
# number.set(int("0"))
entry_player_number.grid(row=2, column=3, rowspan=2)
# specify a default value inside the entry box
# entry_player_number.insert(0,int("2"))
# Add a button for adding players to the game
addPlayerButton = tkinter.ttk.Button(self.root,
text="Enter",
command=addPlayers)
addPlayerButton.grid(row=2, column=4)
self.root.mainloop()
pass
pass
main()
In Summary, I first made two screens. I'm hoping to make these into classes. The first screen (pictured) should get input from the user. Then, the first screen should progress to the second screen.
To do this, I have used the following resources:
Resources for merging this code together into Multiple class based windows and the backend:
Python: Tkinter Class Based Windows
Tkinter - GUI Example Multiple Display Frames
I am working an a tool where-in I am getting the initial user credentials and an unique identifier via Tkinter GUI interface. Post that after a lot of data fetching and processing I would get a report into an excel sheet using xlsxwriter package.
I generally exit/close the tkinter window using destroy() method on click of a button. Here, I want to show the user the status of the report creation in a Tkinter messagebox and then close the main window.
Note: I am using .pyw extension, so that the end user who is using the tool shouldn't see the console. So once the user hits the submit button, I will show a label at the footer of the window saying "Processing ..."
Sample code:
from tkinter import *
#Some other libraries are imported
mScrn = Tk()
mScrn.title("Report Generation Tool v1.0")
mScrn.geometry("200x180")
mScrn.resizable(False, False)
tk_uid_lbl = Label(mScrn, text="MVS1 Username")
tk_uid_lbl.pack()
tk_uid_lbl.place(x=20,y=20)
uid = StringVar()
tk_uid = Entry(mScrn, bd=3, textvariable=uid)
tk_uid.pack()
tk_uid.place(x=150, y=20)
tk_pwd_lbl = Label(mScrn, text="MVS1 Password")
tk_pwd_lbl.pack()
tk_pwd_lbl.place(x=20,y=60)
pwd = StringVar()
tk_pwd = Entry(mScrn, bd=3, show='*', textvariable=pwd)
tk_pwd.pack()
tk_pwd.place(x=150, y=60)
tk_ver_lbl = Label(mScrn, text="Version #")
tk_ver_lbl.pack()
tk_ver_lbl.place(x=20,y=100)
ver = StringVar()
tk_ver=Entry(mScrn, bd=3, textvariable=ver)
tk_ver.pack()
tk_ver.place(x=150, y=100)
tk_sub_button = Button(text='Submit', command = show_footer)
tk_sub_button.pack()
tk_sub_button.place(x=150, y=150)
mScrn.mainloop()
#The data provided in the GUI is used for access and a lot of process goes on
#Close the Tkinter window post the process is done
Thanks in Advance. I am using Python3
I am having a hard time understanding your question. My understanding is that using destroy() is exactly what you are looking for. Use destroy() when you are finished. You basically already answered your own question. I would find it helpful if you could explain your question more thoroughly. I agree with Goyo but I cannot comment.
I don't know how to get the data before closing the mainloop(). In
that aspect once that is closed I cannot show the label on the GUI and
then close with user consent (i.e. after clicking 'ok' in message box)
I don't undestand where is your problem, you can save your data with a lot ways, list, module, object, file, etc.
import tkinter as tk
import random
import threading
import time
# Simulate a process
def get_data(callback):
while True:
if len(data) == 10:
break
time.sleep(.5)
data.append(random.randint(1, 200))
callback()
def wait_end(label, tk_var_end, num=0):
label["text"] = "Processing " + " ." * num
num += 1
if num == 4:
num = 0
if not tk_var_end.get():
mScrn.after(500, wait_end, label, tk_var_end, num)
def execute():
for entry in (tk_uid, tk_pwd, tk_ver):
entry['state'] = tk.DISABLED
tk_sub_button.destroy()
tk_process_lbl = tk.Label(mScrn)
tk_process_lbl.pack()
tk_process_lbl.place(x=150,y=150)
tk_var_end = tk.BooleanVar(False)
wait_end(tk_process_lbl, tk_var_end)
process = threading.Thread(
target=get_data,
kwargs=(dict(callback=lambda: tk_var_end.set(True)))
)
process.start()
mScrn.wait_variable(tk_var_end)
mScrn.after(500, tk_process_lbl.config, dict(text='Process completed'))
mScrn.after(1500, mScrn.quit)
mScrn = tk.Tk()
data = []
mScrn.title("Report Generation Tool v1.0")
mScrn.geometry("400x180")
mScrn.resizable(False, False)
tk_uid_lbl = tk.Label(mScrn, text="MVS1 Username")
tk_uid_lbl.pack()
tk_uid_lbl.place(x=20,y=20)
uid = tk.StringVar()
tk_uid = tk.Entry(mScrn, bd=3, textvariable=uid)
tk_uid.pack()
tk_uid.place(x=150, y=20)
tk_pwd_lbl = tk.Label(mScrn, text="MVS1 Password")
tk_pwd_lbl.pack()
tk_pwd_lbl.place(x=20,y=60)
pwd = tk.StringVar()
tk_pwd = tk.Entry(mScrn, bd=3, show='*', textvariable=pwd)
tk_pwd.pack()
tk_pwd.place(x=150, y=60)
tk_ver_lbl = tk.Label(mScrn, text="Version #")
tk_ver_lbl.pack()
tk_ver_lbl.place(x=20,y=100)
ver = tk.StringVar()
tk_ver= tk.Entry(mScrn, bd=3, textvariable=ver)
tk_ver.pack()
tk_ver.place(x=150, y=100)
tk_sub_button = tk.Button(text='Submit', command = execute)
tk_sub_button.pack()
tk_sub_button.place(x=150, y=150)
mScrn.mainloop()
print(data)
But, you can also make your own class which will inherit of Tk, in this class you could override the quit or destroy method of Tk.
I am using a python 2.7 tkinter gui on a raspberry pi to automate some material testing. For the testing, multiple samples must be tested and it takes time to swap out the samples. I want to prompt text saying something like "Please insert sample one then press enter on keyboard" and have the function pause until enter has been pressed. Instead of pressing enter I could also use a tkinter button. Any ideas without using external libraries? I have tried a while loop in which I try and exit the loop once a button is pressed, but since the loop is running the button does not register.
Sample code (removed lots of code and left what is relevant):
class App:
def __init__(self,master):
#self.WILTRON = Wiltron_54128A_GPIB()
self.var = tk.StringVar()
self.var.trace("w",self.getTest)
self.okbutton = tk.IntVar()
self.okbutton.trace("w",self.OKbutton)
frame = Frame(master)
frame.pack()
#Initial GUI values
self.var.set('Choose Test')
testChoices = ['TEST']
App.testOption = tk.OptionMenu(frame, self.var, *testChoices)
App.testOption.grid(row=0, column=0)
okButton = tk.Button(frame, text=" OK ", command=self.OKbutton).grid(row=2, column=1)
#Test routine functions
def getTest(self, *args):
test = self.var.get()
sf = "IC Network Analyzer"
root.title(sf)
#####
if test == "TEST":
sample1 = self.WILTRON.Sample_Data()
print 'Change out sample then press OK'
#This is where I need to pause until the next sample has been inserted
sample2 = self.WILTRON.Sample_Data()
#ect.
#####
def OKbutton(self):
#Whatever I need to do to make the button exit the pause
Here's a working example that uses a callback to start the test, and a callback to advance each sample.
import Tkinter as tk
class App:
def __init__(self, master):
self.master = root
self.frame = tk.Frame(self.master)
self.okLabel = tk.Label(self.frame, text="Change out sample then press OK")
self.okButton = tk.Button(self.frame, text=" OK ", command=self.nextSample)
self.var = tk.StringVar()
self.var.set('Choose Test')
self.var.trace("w",self.beginTest)
testChoices = ['TEST']
self.testOption = tk.OptionMenu(self.frame, self.var, *testChoices)
self.sampleNumber = 1
self.maxSamples = 5
self.testing = False
self.samples = []
self.updateGUI()
def testSample(self):
# Do whatever you need to do to test your sample
pass
def beginTest(self, *args): # This is called when the user clicks the OptionMenu to begin the test
self.testing = True
sf = "IC Network Analyzer"
self.master.title(sf)
self.testOption.config(state=tk.DISABLED)
self.okButton.config(state=tk.NORMAL)
self.okLabel.config(text="Ready first sample, then press OK")
self.updateGUI()
def nextSample(self): # This is called each time a new sample is tested.
if self.sampleNumber >= self.maxSamples: # If the maximum # of samples has been reached, end the test sequence
self.testing = False
self.sampleNumber = 1
self.testOption.config(state=tk.NORMAL)
self.okButton.config(state=tk.DISABLED)
# You'll want to save your sample data to a file or something here
self.samples = []
self.updateGUI()
else:
self.sampleNumber += 1
if self.var.get() == "TEST":
self.samples.append(self.WILTRON.Sample_Data())
self.okLabel.config(text="Switch to sample #"+str(self.sampleNumber)+" and press OK")
#At this point, the GUI will wait politely for you to push the okButton, before it runs this method again.
#ect.
#####
def updateGUI(self):
self.frame.grid()
self.testOption.grid(row=1, column=1)
if self.testing:
self.okLabel.grid(row=2, column=1)
self.okButton.grid(row=3, column=1)
else:
self.okLabel.grid_remove()
self.okButton.grid_remove()
self.master.update_idletasks()
root = tk.Tk()
a = App(root)
root.mainloop()
Use tkMessageBox
import Tkinter
import tkMessageBox
print "Sample #1"
tkMessageBox.showinfo("Message", "Insert sample and press OK")
print "Sample #2"