H
half.italian
Hi all,
I don't really understand how to properly use threading in my programs,
however I have managed to get by so far using them improperly. Once
again I have come up to what I think is something that won't work
because of the way the program is set up.
I have a long running process running underneath a gui in a different
thread, and a progress bar that updates the status of the operation.
What I would like to do is use something like :
self.progressWindow.protocol('WM_DELETE_WINDOW', self.callback)
and setup the callback to kill the operation and then the window when
the user clicks on the X of the progress window. I've implemented this
in my code, but clicking on the X does nothing until I kill the main
thread (i think), and then my callback is run. I've also had problems
in the past of the gui not refreshing properly, which leads me to
believe that both of these are thread related. Any help would be
immensely appreciated.
~Sean DiZazzo
~~~~~~~~~~~~~~~~~~~
import sys, os, time
libdir = "/usr/local/sw/lib"
sys.path.append(libdir)
import ProgressBarView, Folder, P
from Tkinter import *
from tkFileDialog import askopenfilenames
from tkMessageBox import showerror, showinfo
import pexpect, ssh_session
import P
import Pmw
rootWin = Tk()
class Window(Frame):
label = None
initialdir = "/"
dest = "/tmp"
folder = None
logpath = "/tmp/Send.log"
copyindex = 0
files = []
progressWindow = None
session = None
password = P.P()
ssh = ssh_session.ssh_session("root", "XX.XX.XX.XX",
password.Decrypt(password.sean))
timeout = 30
def __init__(self, parent=None):
Frame.__init__(self, parent)
rootWin.title("Send to Blah")
rootWin.resizable(width=0,height=0)
self.pack()
self.progress_and_log()
f = Frame(self)
openfunc = (lambda self=self, name=None: self.openfolder())
Button(f, text="Choose", command=openfunc).pack(side="left")
self.label = Label(f, text=' <--- Choose files', bg="grey", width=40,
justify='left', anchor='w')
self.label.pack(side="left", anchor='w', padx=5)
f.pack(padx=10, pady=10, side='left', fill='both', anchor='w')
submitfunc = (lambda self=self, name=None: self.submit())
b = Button(self, text="Send", command=submitfunc)
b.pack(side="right", padx=5)
def openfolder(self):
self.files = []
self.files_tuple = askopenfilenames(parent=rootWin, initialdir="/")
for file in self.files_tuple:
self.files.append(file)
self.files.sort()
label = "Click button to send files -->"
self.st.configure(text_state = 'normal')
self.st.clear()
self.st.insert('end', "Files to be copied:\n")
self.st.insert('end', "~~~~~~~~~~~~~~~~~~~\n")
for file in self.files:
self.st.insert('end', os.path.split(file)[-1] + "\n")
self.st.insert('end', " \n \n")
self.st.configure(text_state = 'disabled')
self.label.config(text='Click to send files ---> ', justify='right',
anchor='e')
def callback(self):
"""Need to get the pid here and kill the running process"""
def submit(self):
files = self.files
dest = Folder.Folder(self.dest)
for file in files:
if self.ssh.exists(os.path.join(dest.path,
os.path.split(file)[-1])):
showerror("error", "The file '%s' already exists" %
os.path.join(dest.path, os.path.split(file)[-1]))
return 0
import threading
geometry = None
for file in files:
self.progressWindow = Toplevel(rootWin)
self.progressWindow.protocol('WM_DELETE_WINDOW', self.callback)
self.progressWindow.geometry(geometry)
self.progressWindow.title("Progress")
self.progressWindow.resizable(width=0,height=0)
self.proglabel = Label(self.progressWindow, text='Copying...',
anchor=NW, justify=LEFT, width=30)
self.proglabel.pack(fill=X, expand=1)
self.progressBar =
ProgressBarView.ProgressBarView(self.progressWindow)
self.progressBar.pack(fill=X)
threading.Thread(target=self.threadedCopy,args=(file, dest)).start()
#grab the location from the first window
if geometry is None:
self.progressBar.updateProgress(0)
geometry = self.progressWindow.geometry()
self.incrementProgress(self.progressWindow, file, dest)
self.label.config(text=" <--- Choose files", justify='left',
anchor='w')
self.files=[]
def progress_and_log(self):
self.st = Pmw.ScrolledText(rootWin, borderframe = 1,
usehullsize = 1,
hull_width = 400,
hull_height = 150,
text_wrap='none',
#text_font = fixedFont,
text_padx = 4,
text_pady = 4,
)
self.st.configure(text_state = 'disabled')
self.st.pack(padx = 5, pady = 5, fill = 'both', expand = 1)
def threadedCopy(self, file, dest):
self.ssh.scp(file, os.path.join(dest.path, os.path.split(file)[1]))
def appendToLog(self, src, dest):
dest_size = self.ssh.size(dest.path)
try:
dest_size = float(dest_size)
except:
dest_size = 0
if src.size == dest_size:
status = "SUCCESS"
else:
status = "FAILED"
entry = "%s - %s %s, %s\n" % (time.ctime(time.time()), status,
src.name, src.readableSize)
f = open(self.logpath, 'a')
f.write(entry)
f.close()
self.st.configure(text_state = 'normal')
self.st.insert('end', entry)
self.st.configure(text_state = 'disabled')
def incrementProgress(self, window, file, dest):
import File
src = File.File(file)
dest = File.File(os.path.join(dest.path, os.path.split(file)[-1]))
start = time.time()
p = 0
last_dest = 0
same_count = 0
while p < 100:
d_size = self.ssh.size(dest.path)
try:
float(d_size)
except:
"Couldn't turn %s into a float" % d_size
continue
if last_dest == d_size and same_count == 40:
showerror("error", "Error copying %s\nRemoving the partially
transferred file and continuing..." % dest.path)
self.ssh.ssh("sudo rm %s" % dest.path)
if d_size == None:
d_size = 1000
self.proglabel.config(text=src.name)
p = (float(d_size) / float(src.size)) * 100.0
d_size = self.ssh.size(dest.path)
if last_dest == d_size:
same_count = same_count +1
print "P:", p
self.progressBar.updateProgress(p)
self.update_idletasks()
time.sleep(0.25)
last_dest = d_size
self.appendToLog(src, dest)
window.destroy()
return
if __name__ == "__main__":
Window().mainloop()
I don't really understand how to properly use threading in my programs,
however I have managed to get by so far using them improperly. Once
again I have come up to what I think is something that won't work
because of the way the program is set up.
I have a long running process running underneath a gui in a different
thread, and a progress bar that updates the status of the operation.
What I would like to do is use something like :
self.progressWindow.protocol('WM_DELETE_WINDOW', self.callback)
and setup the callback to kill the operation and then the window when
the user clicks on the X of the progress window. I've implemented this
in my code, but clicking on the X does nothing until I kill the main
thread (i think), and then my callback is run. I've also had problems
in the past of the gui not refreshing properly, which leads me to
believe that both of these are thread related. Any help would be
immensely appreciated.
~Sean DiZazzo
~~~~~~~~~~~~~~~~~~~
import sys, os, time
libdir = "/usr/local/sw/lib"
sys.path.append(libdir)
import ProgressBarView, Folder, P
from Tkinter import *
from tkFileDialog import askopenfilenames
from tkMessageBox import showerror, showinfo
import pexpect, ssh_session
import P
import Pmw
rootWin = Tk()
class Window(Frame):
label = None
initialdir = "/"
dest = "/tmp"
folder = None
logpath = "/tmp/Send.log"
copyindex = 0
files = []
progressWindow = None
session = None
password = P.P()
ssh = ssh_session.ssh_session("root", "XX.XX.XX.XX",
password.Decrypt(password.sean))
timeout = 30
def __init__(self, parent=None):
Frame.__init__(self, parent)
rootWin.title("Send to Blah")
rootWin.resizable(width=0,height=0)
self.pack()
self.progress_and_log()
f = Frame(self)
openfunc = (lambda self=self, name=None: self.openfolder())
Button(f, text="Choose", command=openfunc).pack(side="left")
self.label = Label(f, text=' <--- Choose files', bg="grey", width=40,
justify='left', anchor='w')
self.label.pack(side="left", anchor='w', padx=5)
f.pack(padx=10, pady=10, side='left', fill='both', anchor='w')
submitfunc = (lambda self=self, name=None: self.submit())
b = Button(self, text="Send", command=submitfunc)
b.pack(side="right", padx=5)
def openfolder(self):
self.files = []
self.files_tuple = askopenfilenames(parent=rootWin, initialdir="/")
for file in self.files_tuple:
self.files.append(file)
self.files.sort()
label = "Click button to send files -->"
self.st.configure(text_state = 'normal')
self.st.clear()
self.st.insert('end', "Files to be copied:\n")
self.st.insert('end', "~~~~~~~~~~~~~~~~~~~\n")
for file in self.files:
self.st.insert('end', os.path.split(file)[-1] + "\n")
self.st.insert('end', " \n \n")
self.st.configure(text_state = 'disabled')
self.label.config(text='Click to send files ---> ', justify='right',
anchor='e')
def callback(self):
"""Need to get the pid here and kill the running process"""
def submit(self):
files = self.files
dest = Folder.Folder(self.dest)
for file in files:
if self.ssh.exists(os.path.join(dest.path,
os.path.split(file)[-1])):
showerror("error", "The file '%s' already exists" %
os.path.join(dest.path, os.path.split(file)[-1]))
return 0
import threading
geometry = None
for file in files:
self.progressWindow = Toplevel(rootWin)
self.progressWindow.protocol('WM_DELETE_WINDOW', self.callback)
self.progressWindow.geometry(geometry)
self.progressWindow.title("Progress")
self.progressWindow.resizable(width=0,height=0)
self.proglabel = Label(self.progressWindow, text='Copying...',
anchor=NW, justify=LEFT, width=30)
self.proglabel.pack(fill=X, expand=1)
self.progressBar =
ProgressBarView.ProgressBarView(self.progressWindow)
self.progressBar.pack(fill=X)
threading.Thread(target=self.threadedCopy,args=(file, dest)).start()
#grab the location from the first window
if geometry is None:
self.progressBar.updateProgress(0)
geometry = self.progressWindow.geometry()
self.incrementProgress(self.progressWindow, file, dest)
self.label.config(text=" <--- Choose files", justify='left',
anchor='w')
self.files=[]
def progress_and_log(self):
self.st = Pmw.ScrolledText(rootWin, borderframe = 1,
usehullsize = 1,
hull_width = 400,
hull_height = 150,
text_wrap='none',
#text_font = fixedFont,
text_padx = 4,
text_pady = 4,
)
self.st.configure(text_state = 'disabled')
self.st.pack(padx = 5, pady = 5, fill = 'both', expand = 1)
def threadedCopy(self, file, dest):
self.ssh.scp(file, os.path.join(dest.path, os.path.split(file)[1]))
def appendToLog(self, src, dest):
dest_size = self.ssh.size(dest.path)
try:
dest_size = float(dest_size)
except:
dest_size = 0
if src.size == dest_size:
status = "SUCCESS"
else:
status = "FAILED"
entry = "%s - %s %s, %s\n" % (time.ctime(time.time()), status,
src.name, src.readableSize)
f = open(self.logpath, 'a')
f.write(entry)
f.close()
self.st.configure(text_state = 'normal')
self.st.insert('end', entry)
self.st.configure(text_state = 'disabled')
def incrementProgress(self, window, file, dest):
import File
src = File.File(file)
dest = File.File(os.path.join(dest.path, os.path.split(file)[-1]))
start = time.time()
p = 0
last_dest = 0
same_count = 0
while p < 100:
d_size = self.ssh.size(dest.path)
try:
float(d_size)
except:
"Couldn't turn %s into a float" % d_size
continue
if last_dest == d_size and same_count == 40:
showerror("error", "Error copying %s\nRemoving the partially
transferred file and continuing..." % dest.path)
self.ssh.ssh("sudo rm %s" % dest.path)
if d_size == None:
d_size = 1000
self.proglabel.config(text=src.name)
p = (float(d_size) / float(src.size)) * 100.0
d_size = self.ssh.size(dest.path)
if last_dest == d_size:
same_count = same_count +1
print "P:", p
self.progressBar.updateProgress(p)
self.update_idletasks()
time.sleep(0.25)
last_dest = d_size
self.appendToLog(src, dest)
window.destroy()
return
if __name__ == "__main__":
Window().mainloop()