Skip to content

Instantly share code, notes, and snippets.

@niazangels
Created January 22, 2018 19:11
Show Gist options
  • Save niazangels/7247fbaa9bf09e70c7fe0c2578abc8db to your computer and use it in GitHub Desktop.
Save niazangels/7247fbaa9bf09e70c7fe0c2578abc8db to your computer and use it in GitHub Desktop.
Simple progressbar with Flask + Celery
'''
testing celery progress reporting/polling
* start server
python tempserver.py
* start worker
celery -A tempserver.celery worker -c 1 --loglevel=DEBUG
* browse to localhost:5000/
'''
from flask import Flask, request, render_template_string
from celery import Celery, current_task
from celery.result import AsyncResult
import os
import random
import time
import json
REDIS_SERVER_URL = 'localhost'
CELERY_BROKER_HOST = 'amqp'
celery = Celery(os.path.splitext(__file__)[0],
backend=CELERY_BROKER_HOST,
broker=CELERY_BROKER_HOST + '://')
@celery.task
def slow_proc():
NTOTAL = 10
for i in range(NTOTAL):
time.sleep(random.random() * 2)
current_task.update_state(state='PROGRESS',
meta={'current': i, 'total': NTOTAL})
return 999
app = Flask(__name__)
@app.route('/progress')
def progress():
jobid = request.values.get('jobid')
if jobid:
# GOTCHA: if you don't pass app=celery here,
# you get "NotImplementedError: No result backend configured"
job = AsyncResult(jobid, app=celery)
print(job.state)
print(job.result)
if job.state == 'PROGRESS':
return json.dumps(dict(
state=job.state,
progress=job.result['current'] * 1.0 / job.result['total'],
))
elif job.state == 'SUCCESS':
return json.dumps(dict(
state=job.state,
progress=1.0,
))
return '{}'
@app.route('/enqueue')
def enqueue():
job = slow_proc.delay()
return render_template_string('''\
<style>
#prog {
width: 400px;
border: 1px solid #eee;
height: 20px;
}
#bar {
width: 0px;
background-color: #ccc;
height: 20px;
}
</style>
<h3></h3>
<div id="prog"><div id="bar"></div></div>
<div id="pct"></div>
<script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
<script>
function poll() {
$.ajax("{{url_for('.progress', jobid=JOBID)}}", {
dataType: "json"
, success: function(resp) {
console.log(resp);
$("#pct").html(resp.progress);
$("#bar").css({width: $("#prog").width() * resp.progress});
if(resp.progress >= 0.9) {
$("#bar").css({backgroundColor: "limegreen"});
return;
} else {
setTimeout(poll, 1000.0);
}
}
});
}
$(function() {
var JOBID = "{{ JOBID }}";
$("h3").html("JOB: " + JOBID);
poll();
});
</script>
''', JOBID=job.id)
@app.route('/')
def index():
return render_template_string('''\
<a href="{{ url_for('.enqueue') }}">launch job</a>
''')
if __name__ == '__main__':
app.run(debug=True)
@avnermosh
Copy link

I want to try your celery-flask-progressbar.py example.
I'm new to Gist.
How can I run the code?
Do I have to create an environment?
Thanks

@niazangels
Copy link
Author

Hello @avnermosh - Yes, you do require to have Flask and celery installed- it's best to do this in a separate environment. Additionally, if you look at the code, you'll see that we need a backend running, which is RabbitMQ in this case.

I never thought anybody would stumble upon this gist one day, so I never really documented this- If you're looking for a full tutorial, I suggest you follow this repo: https://github.com/miguelgrinberg/flask-celery-example

@luisl-12
Copy link

Hello, i tried the Miguel Grinberg example and yours and the browser it's stuck everytime when the task is executed. I dont know what it can be. I can execute the task if flask is not used. However when i do it in the browser it blocks.

imagem

in your case it blocks the browser when i click launch job.

Sorry my english is not the best, do you know what it can be ?

Thanks.

@RTO1944
Copy link

RTO1944 commented Oct 4, 2023

When I run your program under PyCharm, I get this config error: celery.exceptions.ImproperlyConfigured: Unknown result backend: 'amqp'. Did you spell that correctly? ('is a Python module, not a backend class.'). How can I get around it? Would appreciate your help. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment