簡體   English   中英

對一組Popen對象進行wait()

[英]wait() on a group of Popen objects

我有許多Popen對象,每個對象代表我已經開始的長期運行命令。 實際上,我不希望這些命令退出。 如果其中任何一個退出,我想等幾秒鍾然后重新啟動。 有一個好的,pythonic方式來做到這一點?

例如:

import random
from subprocess import Popen

procs = list()
for i in range(10):
    procs.append(Popen(["/bin/sleep", str(random.randrange(5,10))]))

一種天真的方法可能是:

for p in procs:
    p.wait()
    print "a process has exited"
    # restart code
print "all done!"

但這不會提醒我第一個退出的過程。 所以我可以試試

for p in procs:
    p.poll()
    if p.returncode is not None:
        print "a process has exited"
        procs.remove(p)
        # restart code
print "all done!"

但是,這是一個緊湊的循環並將消耗CPU。 我想我可以在循環中添加一個time.sleep(1) ,所以它沒有忙碌等待,但我失去了精度。

我覺得應該有一些很好的方式來等待一組pids - 我是對的嗎?

  1. “重新啟動崩潰的服務器”任務非常常見,除非有具體原因,否則可能不應由自定義代碼處理。 請參閱upstartsystemd以及monit

  2. multiprocessing.Pool對象聽起來像一個勝利 - 它會自動啟動進程,甚至在需要時重新啟動它們。 不幸的是,它不是很容易配置。

這是一個老Popen解決方案:

import random, time
from subprocess import Popen


def work_diligently():
    cmd = ["/bin/sleep", str(random.randrange(2,4))]
    proc = Popen(cmd)
    print '\t{}\t{}'.format(proc.pid, cmd) # pylint: disable=E1101
    return proc


def spawn(num):
    return [ work_diligently() for _ in xrange(num) ]


NUM_PROCS = 3
procs = spawn(NUM_PROCS)
while True:
    print time.ctime(), 'scan'
    procs = [ 
        proc for proc in procs
        if proc.poll() is None
    ]
    num_exited = NUM_PROCS - len(procs)
    if num_exited:
        print 'Uhoh! Restarting {} procs'.format(num_exited)
        procs.extend( spawn(num_exited) )
    time.sleep(1)

輸出:

    2340    ['/bin/sleep', '2']
    2341    ['/bin/sleep', '2']
    2342    ['/bin/sleep', '3']
Mon Jun  2 18:01:42 2014 scan
Mon Jun  2 18:01:43 2014 scan
Mon Jun  2 18:01:44 2014 scan
Uhoh! Restarting 2 procs
    2343    ['/bin/sleep', '3']
    2344    ['/bin/sleep', '2']
Mon Jun  2 18:01:45 2014 scan
Uhoh! Restarting 1 procs
    2345    ['/bin/sleep', '2']
Mon Jun  2 18:01:46 2014 scan
Uhoh! Restarting 1 procs
    2346    ['/bin/sleep', '2']
Mon Jun  2 18:01:47 2014 scan
Uhoh! Restarting 2 procs
    2347    ['/bin/sleep', '3']
    2349    ['/bin/sleep', '2']

如果使用posix操作系統,則可以使用os.wait等待任何子進程。 您可以獲得process-id,您可以將其與列表的pid進行比較,以查找已終止的進程:

import random
from subprocess import Popen
import os

procs = {}
for i in range(10):
    proc = Popen(["/bin/sleep", str(random.randrange(5,10))])
    procs[proc.pid] = proc

while procs:
    pid, status = os.wait()
    proc = procs.pop(pid)
    print "process %d has exited" % proc.pid
    # restart code
print "all done!"

扭曲的流程API允許有效地響應流程完成和許多其他條件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM