2013-04-22 79 views
1

我有一些虛擬代碼放在一起,啓動一個進程(exist_view),它調用一個shell腳本,然後通過狀態頁面循環,定期檢查以查看進程是否產生了返回代碼,然後渲染結果。如何用金字塔優雅地處理python子進程

但是,我得到的結果是,子進程會鎖定客戶端上的呈現,直到它完成爲止,這會呈現'客戶端的定期狀態更新'模擬。我真的需要能夠向客戶展示正在進行的事情,因爲最終項目會有幾個連續的子過程運行,其中一些可能需要幾分鐘時間(這是針對定製設備,而不是某個網站)。下面的代碼片段。有什麼建議麼?

請注意,我正在使用Python 2.6.5和Pyramid 1.4。

@view_config(route_name='waiting', renderer='waiting.mako') 
def waiting_view(request, process): 
    while process.poll() == None: 
     time.sleep(1) 
    print str(process.returncode) 
    return {} 

@view_config(route_name='exist', renderer='exist.mako') 
def exist_view(request): 
    process = subprocess.Popen(['bash', '-c', './dummy.sh'], stdout=subprocess.PIPE) 
    return HTTPFound(request.route_url('waiting', process=process)) 
+1

這裏有不止一種方法。另外,它不是金字塔/ Python專有的。一種方法(可能是最簡單的方法,但不是最簡潔的方法)是將任務的進度保存在某個地方(如數據庫),並使用ajax請求在前端輪詢。更復雜的方法是使用消息隊列,工作者以及某種方式將通知推送到客戶端(例如,Server-Sent Events或WebSocket)。 – 2013-04-23 12:42:22

回答

2

我的幻想消失在#pyramid IRC頻道。

對TL; dr爲有3個選項:

  1. 叉的過程,而不是使用子
  2. 使用隊列引擎(如芹菜)
  3. 使用發電機來解析結果,因爲它們進來

下面是進一步闡明聊天記錄:

<phira> hewhocutsdown: that's never going to work 
<phira> hewhocutsdown: I can see what you're trying to do, but the threading/request system doesn't work like that 
* chrisrossi has quit (Ping timeout: 264 seconds) 
<hewhocutsdown> hrm... is there another approach I could take, or is that strictly precluded? 
<phira> hewhocutsdown: what you want is most likely to use one of the queue engines like celery or gearman to run the process from a pool 
<phira> that approach is probably the most normal production approach to take 
<phira> if you're after a simpler, quicker hack you have two options. The first is to fork the whole process and have it write to a file or something, that waiting_view can read from to get status 
<phira> the second is to use a generator as the return on exist_view and let it feed out the results of the process bit by bit as they arrive, effectively turning it into a long poll 
<hewhocutsdown> yeah, I looked at Celery but I don't have enough server control to be able to load it. // the forking idea could be done // what do you mean by a generator? 
<hewhocutsdown> and to clarify; the .sh is basically copying and configuring Xen images 
<hewhocutsdown> so they're simple scripts but they may take a while to respond 
<pdobrogost> graffic: it doesn't need to be stable to be used in trasactions. what you see (or you image you see) is irrelevant here 
<phira> ok, in that case I'd go with the forking thing 
<phira> the one problem you're gonna have is that you can lose track of the processes (ie you fork one, and forget its there and it zombies or similar), you can deal with this in a variety of ways using process pools but they're not really a pyramid issue 
<phira> the key point to remember is that you can't set a variable in one view, and have another view do things with it. Your views are (often) in separate thread contexts and unless you play a very careful game of thread safety they can't talk to each other like that, any info they want to share needs to go through the database or filesystem. 
<hewhocutsdown> yeah, I don't have a db, at present it's just filesystem (calling shell scripts/reading return codes/writing text files). I'll take a stab at prototyping the fork method. Just so I know, how would the generator method work? 
<phira> with the generator you return aresponse that basically returns the lines as they arrive from the script or similar, slowly (so the request takes ages, basically, but starts feeding out information almost immediately). You can then use xhr on the client side to call that url (once) to start the process and read the results as they happen 
<phira> the risk of doing so is that you have no way of restarting it. If the client loses the connection, they cannot re-poll the endpoint because that will start a new process, instead of talk to the old one 
<hewhocutsdown> got it. yes, I did something similar before I switched to using return codes. 
<phira> there are strategies to get around that, but it's rarely worth the effort. 
<hewhocutsdown> alright, I'll look into forking and process pooling. 
<hewhocutsdown> thank you 
<phira> no problem 
<phira> also for what it's worth, this is probably the right place for almost any pyramid related question, the people here know all the things and they're usually around. THat's not always the case for some channels so I figure it's worth saying.