Just looking at the background task, you have odd looking code in there. I’ll comment on the key things I see, others may have more sophisticated comments.
-
You do multiple searches without specifying an order by clause, yet you then take a slice from those results. Unless you specify the order, you’re relying on the database to give you back results in the order you want, but without specifying the order you can’t guarantee it’ll do that.
-
You create a generator comprehension and then take a slice from it. There’s no need for the generator comprehension. For example:
([column['DBT'] for column in app_tables.data.search()][startrow:stoprow])
is designed to give you a list of a specific column between startrow and stoprow. This will do the same (the Anvil search results already functions like a generator):
[column['DBT'] for column in app_tables.data.search()[startrow:stoprow]]
I suspect the Anvil search results will do the slicing more intelligently than the generator, which will have to process all the items up to the ones you want.
- You do the exact same data tables search multiple times. Do it once and reuse the results, e.g.:
results = app_tables.data.search()
[FILE] = ([column['FILE'] for column in results][0:1])
[STATION] = ([column['STATION'] for column in results][0:1])
That should speed things up some, since you don’t need to perform the same query multiple times.
The majority of your time is no doubt taken up by your DBT_AVG
calculation, since it processes over 8,000 rows. I’m assuming there’s some magic reason that you know exactly how many rows will be in the table?
In any case, rather than calculate that average as needed, since you’re importing the contents of that data from an Excel file and are adding each row individually, you should be able to calculate the average as you’re already processing each row in the Excel file. That would prevent the need to calculate it later (unless the contents of the data table can change after the import).
- Your plot isn’t showing because you have code in the client like this:
self.plot_1.figure = anvil.server.call('get_plot')
But what the server function returns is not the plot, but the background task. You need to have some mechanism on the client that waits until the background task is complete before setting the figure. It’s pretty typical to use a timer on the form to check to see if the background task is complete.
When you make the server call that returns the task, you remember the task and start the timer, e.g.:
self.task = anvil.server.call('get_plot')
self.timer_1.interval = 1
Then in the timer function you can check to see if the task is complete:
if self.task.get_return_value():
self.plot_1.figure = self.task.get_return_value()
self.timer_1.interval = 0
That can get way more sophisticated by using the task state to return multiple items, but that gives you the basic idea.