Updating a FloatProgress widget within a thread doesn't work anymore in a notebook

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Updating a FloatProgress widget within a thread doesn't work anymore in a notebook

steffenl
I am writing a application that calculates some physical beheaviour based on user defined models. These calculations have a high workload. Therefore the user needs some information over the calculation progress.
It is very difficult to show the progress in a Jupyter notebook. With text printing the output can not easily get flushed because of the notebooks output handling. Therefore I used the FloatProgress widget out of the IPython.html module. I used a threading.Timer to update the widgets value. This no longer works in the updated ipython version 3.2.
The widget does not show the actual value. It updates its visual representation only once after the code in the nodebook cell is already processed.
How is it possible to update the visual representation of the widget during the computation? The following simplified code can show the problem if it runs in a notebook cell:

from IPython.html import widgets
from IPython.display import display
import threading

class Counter:
    """Simulates a task with heavy workload.
    The 'value' attribut holds the state of the progress.
    If the value of 'value' reaches the value of the 'max' attribut,
    the work is done."""
   
    def __init__(self, max):
        self.max = max
        self.value = 0
       
    def count(self):
        for i in xrange(self.max + 1):
            for _ in xrange(self.max):
                self.value = i
   

class ProgressBar(widgets.FloatProgress):  
   
    def __init__(self, counter):
        super(ProgressBar, self).__init__()        
        self.max = counter.max
        self.counter = counter
        display(self)
        self.show_progress()

    def show_progress(self):
        self._timer = (
            threading.Timer(interval=1.0,
                            function=self.show_progress)) # restart timer
        self._timer.daemon = True # kill thread at shut down of main process        
        self.value = self.counter.value # here, the bar should visually respond
        self._timer.start()
        if self.value >= self.max:
            self.bar_style = 'success'            
            self._timer.cancel()
           

c = Counter(10000)
s = ProgressBar(c)
c.count()