From time to time at work I use a little swing Jython shell to do various and sundry interactive tasks against our system ... either poking at vm-local code in development or against one of the runtime development or staging instances. It's quite useful when it is.
One thing I often find myself doing is processing some chunk of data, which sometimes can take either a good chunk of -- or unknown amount of -- time. The simple implementation of my little jython shell blocks the UI while the python is processing, which is less than ideal for long-running jobs. I've done various ad-hoc threaded solutions for this before, but finally generalized it today.
AsyncMap functions like map, but asynchronously. As it applies the given function to the elements of the given list, it will update a JLabel with its position in the list, as well as the last- and average-times taken processing the elements.
The one potential dependence on my scenario it has is that the global win is expected to contain the JFrame of the UI; but if you supply it another JLabel already placed in the UI appropriately, &c., it'll happily use that.
from java.lang import Runnable
class AsyncMap (Runnable):
'''asynchronous map; reporting position and time-stats to given ui label.'''
def init(self, fn, inList, label = None):
from javax.swing import JLabel
from java.lang import Thread
self.fn = fn
self.inList = inList
self.outList = []
self.errs = []
if not label:
label = JLabel('--- uninit ---')
win.contentPane.add(label)
win.pack()
self.label = label
self.thread = Thread(self)
def start(self):
self.thread.start()
def run(self):
from java.lang import System
totalTime = 0
self.label.text = '0/%d' % (len(self.inList))
for idx,item in [(i,self.inList[i]) for i in range(len(self.inList))]:
start = System.currentTimeMillis()
res = None
try:
res = self.fn(item)
except:
self.errs.append("error at %d" % (idx))
end = System.currentTimeMillis()
self.outList.append(res)
time = end-start
totalTime = totalTime + time
avgTime = totalTime / (idx+1)
self.label.text = '%d / %d - last: %f, avg: %f' % (idx+1, len(self.inList), time, avgTime)
self.label.text = 'DONE: %s' % (self.label.text)