2012-09-07 117 views
6

我必須在燒瓶應用程序中做一些長時間的工作。我想做異步。剛開始工作,然後從javascript中檢查狀態。燒瓶長例程

我試着這樣做:

@app.route('/sync') 
def sync(): 
    p = Process(target=routine, args=('abc',)) 
    p.start() 

    return "Working..." 

但是,這也創造解散gunicorn工人。

如何解決?我應該使用像芹菜一樣的東西嗎?

回答

11

有很多選項。你可以開發自己的解決方案,使用芹菜或扭曲(我確信有更多的已經制作的選項,但那些是最常見的)。

開發您的內部解決方案並不困難。當一個任務到達你在與任務ID和狀態的數據庫中插入一行

  • :您可以使用multiprocessing模塊Python標準庫。
  • 然後啓動一個進程來執行完成時更新行狀態的工作。
  • 你可以有一個視圖來檢查任務是否完成,實際上只是檢查相應的狀態。

當然,你必須考慮你想存儲計算結果的位置以及錯誤發生的情況。

與芹菜一起也很容易。它看起來像下面這樣。 要定義一個函數來異步執行:

@celery.task 
def mytask(data): 

    ... do a lot of work ... 

然後,而不是直接調用的任務,像mytask(data),這將執行它馬上,使用delay方法:

result = mytask.delay(mydata) 

最後,可以檢查結果是否可用ready

result.ready() 

但是,記住那要使用芹菜你必須運行外部工人過程。

我還沒有看過Twisted,所以我不能告訴你它是否比這更復雜或更復雜(但它應該也可以做你想做的事情)。

在任何情況下,任何這些解決方案都應該在Flask中正常工作。如果您使用Javascript,檢查結果根本不在於。只需使檢查狀態的視圖返回JSON(您可以使用Flask的jsonify)。

+0

那麼,我真的擁有你所說的關於在DB中存儲結果的一切。實施我自己的解決方案時遇到的主要問題是,當我使用'multiprocessing'時,會導致gunicorn工作者失效。 – sashab

+0

糟糕,對不起,我誤解了你的問題。看起來問題在於你的父進程在return語句之後終止,這有效地殺死了你剛剛創建的子進程。爲了避免這種情況,你只需在父進程退出之前守護進程(即分離它)[python-daemon](http://pypi.python.org/pypi/python-daemon/) – pacha

+0

我得到了'ValueError:I當在多處理中使用時,關閉文件上的/ O操作。看起來我需要使用Popen。設置'Process()。daemon = True'也沒有幫助。 – sashab

2

我會使用消息代理(如rabbitmq或activemq)。燒瓶過程會將作業添加到消息隊列中,並且長時間運行的工作進程(或者池或工作進程)會將作業從隊列中取出來完成它們。工作進程可以更新數據庫以允許瓶服務器知道作業的當前狀態並將這些信息傳遞給客戶端。

使用芹菜似乎是一個很好的方法來做到這一點。