如何在 python Flask(不是 Django!)上完成芹菜工作后重定向
How to redirect after celery work done on python Flask (not Django!)
我有意的完整代码是一个网站从 youtube 视频获取并转换为 mp3,将其保存到 S3,然后 return S3 link 给用户。
因为我想在低性能的 EC2 上使用(省钱)并且不阻止很多人同时使用它所以我使用 celery 异步进行。
芹菜完成工作后,我可以执行回调函数。但是它只显示在终端上,我如何(显示它来替换)重定向等待屏幕?
from flask import Flask, render_template, request
from celery import Celery
import youtube_dl
app = Flask(__name__)
app.config['CELERY_BROKER_URL'] = 'redis://:password@redis-YYYY.cloud.redislabs.com:YYYY/0'
app.config['CELERY_RESULT_BACKEND'] = 'redis://:password@redis-YYYY.cloud.redislabs.com:YYYY/0'
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
def done_download_hook(d):
if d['status'] == 'finished':
print('Done downloading, now converting ...')
ydl_opts = {
'format': 'bestaudio/best',
'outtmpl': '%(id)s.%(ext)s',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
'progress_hooks': [done_download_hook],
}
@celery.task(bind=True)
def download_task(self, link, ydl_opts):
# some long running task here
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download([link])
# and copy converted file to S3, return/get S3 link
# I could handle the process from EC2 to S3.
@app.route('/')
def my_form():
return render_template('hello.html')
# I try some decorators @app.XXXXX but no success.
def test_callback():
print('it worked and run until here')
# should redirect user to S3 link, or redirect the page with link to click
# How can I do that ?
return 'http://...'
@app.route('/', methods=['POST'])
def my_form_post():
download_link = request.form['text']
# download_task.delay(download_link, ydl_opts)
download_task.apply_async((download_link, ydl_opts),link=test_callback())
return "please waiting, after done converting, we would redirect you to the link"
由于 celery 运行s 任务是一个单独的进程(或多个,如果您 运行 celery 的多个实例),并且您选择了异步体验,以确定何时执行任务完成后,浏览器上的页面将不得不进行轮询(即通过 AJAX)。这意味着它将需要一些可用于查询任务 status/results 的 ID。使用的最简单的 id 是在 .delay()
执行任务时获得的对象中返回的那个。在呈现页面时传递它,以便可以进行 AJAX 调用。
处理调用的视图方法会做类似
的事情
from celery.result import AsyncResult
@app.route('/taskstatus')
def taskstatus(uuid):
result = AsyncResult(uuid)
return HttpResponse(json.dumps({'done': result.ready()}),
content_type='application/json')
当页面看到 done: true
时,它可以做任何事情(重定向、更改元素的文本或颜色,...)
我有意的完整代码是一个网站从 youtube 视频获取并转换为 mp3,将其保存到 S3,然后 return S3 link 给用户。
因为我想在低性能的 EC2 上使用(省钱)并且不阻止很多人同时使用它所以我使用 celery 异步进行。
芹菜完成工作后,我可以执行回调函数。但是它只显示在终端上,我如何(显示它来替换)重定向等待屏幕?
from flask import Flask, render_template, request
from celery import Celery
import youtube_dl
app = Flask(__name__)
app.config['CELERY_BROKER_URL'] = 'redis://:password@redis-YYYY.cloud.redislabs.com:YYYY/0'
app.config['CELERY_RESULT_BACKEND'] = 'redis://:password@redis-YYYY.cloud.redislabs.com:YYYY/0'
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
def done_download_hook(d):
if d['status'] == 'finished':
print('Done downloading, now converting ...')
ydl_opts = {
'format': 'bestaudio/best',
'outtmpl': '%(id)s.%(ext)s',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
'progress_hooks': [done_download_hook],
}
@celery.task(bind=True)
def download_task(self, link, ydl_opts):
# some long running task here
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
ydl.download([link])
# and copy converted file to S3, return/get S3 link
# I could handle the process from EC2 to S3.
@app.route('/')
def my_form():
return render_template('hello.html')
# I try some decorators @app.XXXXX but no success.
def test_callback():
print('it worked and run until here')
# should redirect user to S3 link, or redirect the page with link to click
# How can I do that ?
return 'http://...'
@app.route('/', methods=['POST'])
def my_form_post():
download_link = request.form['text']
# download_task.delay(download_link, ydl_opts)
download_task.apply_async((download_link, ydl_opts),link=test_callback())
return "please waiting, after done converting, we would redirect you to the link"
由于 celery 运行s 任务是一个单独的进程(或多个,如果您 运行 celery 的多个实例),并且您选择了异步体验,以确定何时执行任务完成后,浏览器上的页面将不得不进行轮询(即通过 AJAX)。这意味着它将需要一些可用于查询任务 status/results 的 ID。使用的最简单的 id 是在 .delay()
执行任务时获得的对象中返回的那个。在呈现页面时传递它,以便可以进行 AJAX 调用。
处理调用的视图方法会做类似
的事情from celery.result import AsyncResult
@app.route('/taskstatus')
def taskstatus(uuid):
result = AsyncResult(uuid)
return HttpResponse(json.dumps({'done': result.ready()}),
content_type='application/json')
当页面看到 done: true
时,它可以做任何事情(重定向、更改元素的文本或颜色,...)