V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
fanne
V2EX  ›  Django

django celery 回调问题请教

  •  
  •   fanne · 2017-12-20 13:30:45 +08:00 · 5156 次点击
    这是一个创建于 2564 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有个执行shell脚本的函数,因为执行时间比较长,大概 5 分钟左右,所以我用了 celery 做异步处理,不然页面一直卡着在加载情况。

    task_work.py文件

    @celery_app.task
    def ssh_key(host,shell,action_info):
    	#执行脚本的一些操作
    

    views.py文件里面调用这个任务

    from task_work import ssh_key
    abc = ssh_key.delay(info.public_ip,cmd,action_info)
    

    好了,问题来了。 这个异步任务可以正常丢后台运行,那么我现在要获得这个异步任务的结果要怎么处理?

    我试过以下一些方式,但都不行。

    按照官方做法,可以通过

    abc.result 获得结果
    但这个的前提是
    abc.state == 'SUCCESS'才行
    

    所以我处理方式

    from task_work import ssh_key
    abc = ssh_key.delay(info.public_ip,cmd,action_info)
    while abc.state != 'SUCCESS':
    	time.sleep(1)
    print abc.result
    

    这么处理结果,把异步的又转为同步的

    后来想着把time.sleep()也丢到一个新的异步任务中,处理方式如下

    task_work.py文件新增一个任务

    @celery_app.task
    def result_state(task_id):
    	print task_id
    	print AsyncResult(task_id).state
        ##后面接 time.sleep()等一些操作
    

    views.py文件里面也新增一个调用

    abc = ssh_key.delay(info.public_ip,cmd,action_info)
    print abc.id
    
    result_state.delay(abc.id)
    
    

    然而也并不行,报以下错误信息:

    如果直接在views.py里面打印 id,state 是有值

    abc = ssh_key.delay(info.public_ip,cmd,action_info)
    print abc.id
    print type(abc.id)
    
    from celery.result import AsyncResult
    print AsyncResult(abc.id).ready()
    print AsyncResult(abc.id).state
    
    

    各位大神,这是为何呢

    4 条回复    2017-12-21 11:17:52 +08:00
    GurdZain
        1
    GurdZain  
       2017-12-20 13:48:46 +08:00
    zhanghb
        2
    zhanghb  
       2017-12-20 15:35:03 +08:00
    我之前做过一个项目是把获取到的 id, 直接放 context 里面 return 到 template 里面。然后页面上的 js 每隔几秒钟 ajax 的方式问一下后端的 view 看看 state 是否已经 success 了。

    不过也没去尝试过其他的办法,不知道有没有更方便友好的。
    fanne
        3
    fanne  
    OP
       2017-12-20 16:13:03 +08:00
    @GurdZain @zhanghb
    celery 4.0 之后可以用下列方式,刚刚试了,有返回了

    ```
    # tasks.py
    class MyTask(Task):
    def on_success(self, retval, task_id, args, kwargs):
    print 'task done: {0}'.format(retval)
    return super(MyTask, self).on_success(retval, task_id, args, kwargs)
    def on_failure(self, exc, task_id, args, kwargs, einfo):
    print 'task fail, reason: {0}'.format(exc)
    return super(MyTask, self).on_failure(exc, task_id, args, kwargs, einfo)

    @app.task(base=MyTask)
    def add(x, y):
    return x + y
    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1098 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 19:03 · PVG 03:03 · LAX 11:03 · JFK 14:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.