Communicating progress to the user during long running calculations and optimizations is important. Users often get annoyed when they only see this message for 20 minutes or more:
Also an end user could start doubting if the calculation is still running and is not stuck or crashed.
For this purpose, progress messages were introduced. I would like to show some ways to inform the end user of the progress during calculations.
Showing progress using the total number of calculations and the percentage argument on the progress message:
def calculation(self, **kwargs):
# get items to be calculated
calculations_items = get_calculation_items()
# check how many calculations need to be performed and estimate the total time
total_calculations = len(calculations_items)
estimated_time = timedelta(seconds=1) * total_calculations
for i, item in enumerate(calculations_items):
# make progress message
progress_message(f"Calculation {i + 1}/{total_calculations} (estimated time: {estimated_time})",
percentage=(i / total_calculations) * 100)
some_awesome_calculation(item)
Here also an estimation is given of the total time all calculations will take. This allows the end user to do something else and come back when all calculations are finished.
Intermediate results
You could also share some intermediate results with the end user.
def calculation(self, **kwargs):
# get items to be calculated
calculations_items = get_calculation_items()
# check how many calculations need to be performed and estimate the total time
total_calculations = len(calculations_items)
estimated_time = timedelta(seconds=1) * total_calculations
last_result = None
for i, item in enumerate(calculations_items):
# make progress message
message = f"Calculation {i + 1}/{total_calculations} (estimated time: {estimated_time})"
if last_result:
# Concat base message with last result message
message = message + " \n \n" + last_result
progress_message(message,
percentage=(i / total_calculations) * 100)
result = some_awesome_calculation(item)
last_result = f"The following calculation is performed \n" \
f"Input: some_input_parameters \n" \
f"Result: {result}kNm"
Resulting in:
Spice it up with ASCII art
You could even consider spicing the progress message up with a little ASCII art. We can make a train move along the bottom of the message using the following code:
First, we generate the ASCII art using the following function:
def get_train(i):
padding = " " * (i % 45)
train = f"{padding}____ \n " \
f"{padding} |DD|____T_ \n " \
f"{padding} |_ |_____|< \n " \
f"{padding} @-@-@-oo\\ \n "
return train
This function takes the loop variable i
to generate a padding string. The padding is added to make the train move from left to right.
Using the train, the progress message is constructed:
for i, item in enumerate(calculations_items):
moving_train = get_train(i)
# make progress message
message = f"Calculation {i + 1}/{total_calculations} (estimated time: {estimated_time})"
message = message + " \n \n" + moving_train
progress_message(message,
percentage=(i / total_calculations) * 100)
result = some_awesome_calculation(item)
Result:
I hope this inspires you to implement some awesome progress messages that keep the end user both informed and entertained. Please share your progress message design below this post!