flexx
flexx copied to clipboard
How to execute a long calculation (server side)?
Hi almarklein,
I'm looking for a way to execute a long calculation and not freeze the application.
Here is the situation: I have a website where I can drop an excel file which is transferred to my server to be analysed. Once the server (PyWidget) receives the file, it does an analysis and then returns the results to the client in the form of a graph.
So my analysis function is in a @event.reaction('input.filecontent') in my Main(PyWidget). But as the analysis takes a long time, the flexx app feezes and loose the connection (on the client side who sees the server as unresponsive).
Can I start a thread to do the work on the server and if so how can I get the result back into an event or a reaction so results get transferred back to the client? Any suggestion/examples?
Thanks,
Yes, I would probably do the work in a separate thread. When it's done, you can let it call an action to bring the result back into the main threads event system. This can be e.g. an action on that pyWidget.
See https://flexx.readthedocs.io/en/stable/event/api.html#flexx.event.action for details.
Thank you almarklein. Sadly I was not able to call the @event.action function directly (could not figure it out). I rather found another way that seem simpler.
I added the following within my Main(PyWidget), it is triggered by the reception of content of an excel file from the client browser:
@event.reaction('input.filecontent')
def __source_changed(self, *events):
if "allow_reconnect" not in events[0]: # skip the first one
pos = self.input.filecontent.find("base64,")
content = base64.b64decode(self.input.filecontent[pos+7:])
with tempfile.NamedTemporaryFile(suffix=".xlsx", mode='wb', delete=True) as f:
n=f.write(content)
temp2 = open(f.name, "rb", opener=os_ex.temp_opener)
mm = mmap.mmap(temp2.fileno(), 0, access=mmap.ACCESS_READ)
engine = ExcelFileParser(mm)
def thread():
# do the calculations
mem_file = io.BytesIO()
zoom=0.5
PlotEfficiency.plot(engine, mem_file, figsize=(int(16*zoom),int(8*zoom)), format='png')
plot_data = base64.b64encode(mem_file.getvalue()).decode('utf-8')
def report():
# report on results
self.graph.set_html(f'<img src="data:image/png;base64,{plot_data}" alt="broken" />')
self.tab.set_current(self.graph)
event.loop.call_soon(report)
threading.Thread(target=thread).start()
The Main(PyWidget) contains the graph and tab properties that are changed withing the report function.
It maybe worth it to add the event.loop.call_soon(...) to the documentation as this function can be called safely within a thread to change PyWidget properties.
Right, that should also work :) That function is documented here, but it's part of the flexx.event subpackage, so perhaps easy to overlook.