python - Don't allow function to make Tk GUI hang -
so have program doing following:
- connects mysql database , extracts table ip addresses
- store addresses in list
- for every ip in list, depeding on user preference, via sockets, send or receive files ip address
so, lets have send() function, starts when press button function , this:
for host in ip_list: socket.connect((host,5005))... socket.send(data)... now when server active, code works , copies fast. however, working on code polling, , when server not up, , client cannot connect, code performs rather slow, , gui hangs (example when list has 25ish ip-s function needs connect to).
so want is socket.connect((host,5005)) in thread (or not hang gui)
now, tried threading, acts strange. never works tkinter, since besides upper code lines, have tk.progressbar , few other tk things in function.
i have no idea how multiprocessing, , apparently, has no effect on io hangs.
anybody can provide me ideas?
here how tried threading:
def connect(): global host global socket socket.connect((host,5005)) def my_original_function(): global host global socket t1=threading.thread(target=connect) host in ip_list: t1.start() t1.join()
it relatively simple start more 1 thing in multiprocessing. stick in 1 class keep connected. 1 caveat create 1 tk() class instance only. more 1 causes problems. time.sleep() used in start_running function instead of after() simulate 1 thread hanging. if going use tkinter , more advanced programming, using classes simplify life imho.
from multiprocessing import process import time try: import tkinter tk ## python 2.x except: import tkinter tk ## python 3.x class progressbar(): def __init__(self, root): self.root=root self.root.geometry("75x50+900+100") self.ctr=25 def mainloop(self): self.root.mainloop() def start_countdown(self): """ separate process in separate gui """ self.root.withdraw() self.top_count=tk.toplevel(self.root) self.top_count.geometry("75x50+750+50") self.label_ctr = tk.intvar() self.label_ctr.set(self.ctr) label = tk.label(self.top_count, textvariable=self.label_ctr) label.pack() if self.ctr > 0: self.top_count.after(750, self.update) def start_running(self): """ create progress bar widget """ self.top=tk.toplevel(self.root, takefocus=true) self.top.title("progress bar") self.top.geometry("+700+200") canvas = tk.canvas(self.top, width=261, height=60, bg='lightgray') canvas.pack() rc2 = canvas.create_rectangle(15, 20, 243, 50, outline='blue', fill='lightblue') rc1 = canvas.create_rectangle(24, 20, 34, 50, outline='white', fill='blue') total=100 x = 5 ## use after() while countdown running (self.ctr > 0) ## avoid dangling after() when program terminates while self.ctr: ## move small rectangle +5 or -5 units total += x if total > 311: x = -5 elif total < 100: x = 5 time.sleep(0.2) canvas.move(rc1, x, 0) canvas.update() def update(self): self.ctr -= 1 self.label_ctr.set(self.ctr) if self.ctr > 0: self.top_count.after(750, self.update) else: ## sleep allow remaining after() execute ## can use self.root.after_cancel(id) self.top_count.after(500, self.root.destroy) ## destroy root when ctr==0 root = tk.tk() pb=progressbar(root) pr1=process(target=pb.start_countdown(), args=()) pr1.start() pr2=process(target=pb.start_running(), args=()) pr2.start() ## start mainloop in separate process function of class ## don't know if necessary or not ## theory is, detached other 2 processes , ## can react both independently ## mainloop() process can killed=shut down pr3=process(target=pb.mainloop(), args=()) pr3.start() ## safety clean pr1.terminate() pr2.terminate() pr3.terminate()
Comments
Post a Comment