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.progressWi ndow.protocol(' WM_DELETE_WINDO W', 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 askopenfilename s
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.X X",
password.Decryp t(password.sean ))
timeout = 30
def __init__(self, parent=None):
Frame.__init__( self, parent)
rootWin.title(" Send to Blah")
rootWin.resizab le(width=0,heig ht=0)
self.pack()
self.progress_a nd_log()
f = Frame(self)
openfunc = (lambda self=self, name=None: self.openfolder ())
Button(f, text="Choose", command=openfun c).pack(side="l eft")
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=submitf unc)
b.pack(side="ri ght", padx=5)
def openfolder(self ):
self.files = []
self.files_tupl e = askopenfilename s(parent=rootWi n, initialdir="/")
for file in self.files_tupl e:
self.files.appe nd(file)
self.files.sort ()
label = "Click button to send files -->"
self.st.configu re(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(f ile)[-1] + "\n")
self.st.insert( 'end', " \n \n")
self.st.configu re(text_state = 'disabled')
self.label.conf ig(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(s elf.dest)
for file in files:
if self.ssh.exists (os.path.join(d est.path,
os.path.split(f ile)[-1])):
showerror("erro r", "The file '%s' already exists" %
os.path.join(de st.path, os.path.split(f ile)[-1]))
return 0
import threading
geometry = None
for file in files:
self.progressWi ndow = Toplevel(rootWi n)
self.progressWi ndow.protocol(' WM_DELETE_WINDO W', self.callback)
self.progressWi ndow.geometry(g eometry)
self.progressWi ndow.title("Pro gress")
self.progressWi ndow.resizable( width=0,height= 0)
self.proglabel = Label(self.prog ressWindow, text='Copying.. .',
anchor=NW, justify=LEFT, width=30)
self.proglabel. pack(fill=X, expand=1)
self.progressBa r =
ProgressBarView .ProgressBarVie w(self.progress Window)
self.progressBa r.pack(fill=X)
threading.Threa d(target=self.t hreadedCopy,arg s=(file, dest)).start()
#grab the location from the first window
if geometry is None:
self.progressBa r.updateProgres s(0)
geometry = self.progressWi ndow.geometry()
self.incrementP rogress(self.pr ogressWindow, file, dest)
self.label.conf ig(text=" <--- Choose files", justify='left',
anchor='w')
self.files=[]
def progress_and_lo g(self):
self.st = Pmw.ScrolledTex t(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.configu re(text_state = 'disabled')
self.st.pack(pa dx = 5, pady = 5, fill = 'both', expand = 1)
def threadedCopy(se lf, file, dest):
self.ssh.scp(fi le, os.path.join(de st.path, os.path.split(f ile)[1]))
def appendToLog(sel f, src, dest):
dest_size = self.ssh.size(d est.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(tim e.time()), status,
src.name, src.readableSiz e)
f = open(self.logpa th, 'a')
f.write(entry)
f.close()
self.st.configu re(text_state = 'normal')
self.st.insert( 'end', entry)
self.st.configu re(text_state = 'disabled')
def incrementProgre ss(self, window, file, dest):
import File
src = File.File(file)
dest = File.File(os.pa th.join(dest.pa th, os.path.split(f ile)[-1]))
start = time.time()
p = 0
last_dest = 0
same_count = 0
while p < 100:
d_size = self.ssh.size(d est.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("erro r", "Error copying %s\nRemoving the partially
transferred file and continuing..." % dest.path)
self.ssh.ssh("s udo 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(d est.path)
if last_dest == d_size:
same_count = same_count +1
print "P:", p
self.progressBa r.updateProgres s(p)
self.update_idl etasks()
time.sleep(0.25 )
last_dest = d_size
self.appendToLo g(src, dest)
window.destroy( )
return
if __name__ == "__main__":
Window().mainlo op()
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.progressWi ndow.protocol(' WM_DELETE_WINDO W', 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 askopenfilename s
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.X X",
password.Decryp t(password.sean ))
timeout = 30
def __init__(self, parent=None):
Frame.__init__( self, parent)
rootWin.title(" Send to Blah")
rootWin.resizab le(width=0,heig ht=0)
self.pack()
self.progress_a nd_log()
f = Frame(self)
openfunc = (lambda self=self, name=None: self.openfolder ())
Button(f, text="Choose", command=openfun c).pack(side="l eft")
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=submitf unc)
b.pack(side="ri ght", padx=5)
def openfolder(self ):
self.files = []
self.files_tupl e = askopenfilename s(parent=rootWi n, initialdir="/")
for file in self.files_tupl e:
self.files.appe nd(file)
self.files.sort ()
label = "Click button to send files -->"
self.st.configu re(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(f ile)[-1] + "\n")
self.st.insert( 'end', " \n \n")
self.st.configu re(text_state = 'disabled')
self.label.conf ig(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(s elf.dest)
for file in files:
if self.ssh.exists (os.path.join(d est.path,
os.path.split(f ile)[-1])):
showerror("erro r", "The file '%s' already exists" %
os.path.join(de st.path, os.path.split(f ile)[-1]))
return 0
import threading
geometry = None
for file in files:
self.progressWi ndow = Toplevel(rootWi n)
self.progressWi ndow.protocol(' WM_DELETE_WINDO W', self.callback)
self.progressWi ndow.geometry(g eometry)
self.progressWi ndow.title("Pro gress")
self.progressWi ndow.resizable( width=0,height= 0)
self.proglabel = Label(self.prog ressWindow, text='Copying.. .',
anchor=NW, justify=LEFT, width=30)
self.proglabel. pack(fill=X, expand=1)
self.progressBa r =
ProgressBarView .ProgressBarVie w(self.progress Window)
self.progressBa r.pack(fill=X)
threading.Threa d(target=self.t hreadedCopy,arg s=(file, dest)).start()
#grab the location from the first window
if geometry is None:
self.progressBa r.updateProgres s(0)
geometry = self.progressWi ndow.geometry()
self.incrementP rogress(self.pr ogressWindow, file, dest)
self.label.conf ig(text=" <--- Choose files", justify='left',
anchor='w')
self.files=[]
def progress_and_lo g(self):
self.st = Pmw.ScrolledTex t(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.configu re(text_state = 'disabled')
self.st.pack(pa dx = 5, pady = 5, fill = 'both', expand = 1)
def threadedCopy(se lf, file, dest):
self.ssh.scp(fi le, os.path.join(de st.path, os.path.split(f ile)[1]))
def appendToLog(sel f, src, dest):
dest_size = self.ssh.size(d est.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(tim e.time()), status,
src.name, src.readableSiz e)
f = open(self.logpa th, 'a')
f.write(entry)
f.close()
self.st.configu re(text_state = 'normal')
self.st.insert( 'end', entry)
self.st.configu re(text_state = 'disabled')
def incrementProgre ss(self, window, file, dest):
import File
src = File.File(file)
dest = File.File(os.pa th.join(dest.pa th, os.path.split(f ile)[-1]))
start = time.time()
p = 0
last_dest = 0
same_count = 0
while p < 100:
d_size = self.ssh.size(d est.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("erro r", "Error copying %s\nRemoving the partially
transferred file and continuing..." % dest.path)
self.ssh.ssh("s udo 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(d est.path)
if last_dest == d_size:
same_count = same_count +1
print "P:", p
self.progressBa r.updateProgres s(p)
self.update_idl etasks()
time.sleep(0.25 )
last_dest = d_size
self.appendToLo g(src, dest)
window.destroy( )
return
if __name__ == "__main__":
Window().mainlo op()
Comment