2010-07-07 15 views
11

Paralel olarak bazı alt işlemlerden python çalıştırıyorum. Her alt işlem bitene kadar beklemek istiyorum. Zarif olmayan bir çözüm yapıyorum: Birden çok alt işlem gerçekleştirebilen bir sınıf var mı? Sorun, wait yönteminin programımı engellemesidir.Alt işlemlerin bitişini birden çok paralel iş ile bekle

güncelleme: Ben hesaplaması sırasında ilerleme göstermek istiyorum: Böyle bir şey "4/7 alt işlemi bitmiş ..."

Eğer root C++ komut dosyası derlemek ve çalıştırmak iseniz.

cevap

4

Böyle bir şey yapabileceğini:

runcodes = ["script1.C", "script2.C"] 

ps = [] 
for script in runcodes: 
    args = ["root", "-l", "-q", script] 
    p = subprocess.Popen(args) 
    ps.append(p) 

for p in ps: 
    p.wait() 

süreçler paralel olarak çalışır ve sonunda bunların tümü için bekleyeceğim.

+4

evet, sorun, ilk alt işlemin çok yavaş olduğunu, p ilk 'ps'ye eşit olduğunu ve python'un beklediğinden yüzeyler; python, ilk hariç tüm alt süreçleri yazamaz. –

9

Platformunuz Windows değilse, büyük olasılıkla alt işlemleriniz için stdout borularına karşı seçim yapabilirsiniz. Kayıtlı dosya tanımlayıcıları

  • Bir
  • anket kez (bu durumda, biz altişlem en stdout'u borusunda bir mesele ilgilendiğiniz) bir I/O etkinliği vardır: ya kadar Uygulamanız sonra bloke edecek dışarı

Sigara tenli aşımı Linux 2.6.xx ile epoll kullanarak örnek:

import subprocess 
import select 

poller = select.epoll() 
subprocs = {} #map stdout pipe's file descriptor to the Popen object 

#spawn some processes 
for i in xrange(5): 
    subproc = subprocess.Popen(["mylongrunningproc"], stdout=subprocess.PIPE) 
    subprocs[subproc.stdout.fileno()] = subproc 
    poller.register(subproc.stdout, select.EPOLLHUP) 

#loop that polls until completion 
while True: 
    for fd, flags in poller.poll(timeout=1): #never more than a second without a UI update 
     done_proc = subprocs[fd] 
     poller.unregister(fd) 
     print "this proc is done! blah blah blah" 
     ... #do whatever 
    #print a reassuring spinning progress widget 
    ... 
    #don't forget to break when all are done 
+0

Bu temiz! Mylongrunningproc çalışırken "subproc.stdout" terminaline yazdırmanın bir yolu var mı? – unutbu

+0

Akla ilk gelen şey aynı zamanda giriş olayları için stdout borularını kaydetmektir - 'poller.register (subproc.stdout, select.EPOLLHUP | select.EPOLLIN)'. Daha sonra, eğer yapabilirseniz, '' flag & select.EPOLLIN: print done_proc.stdout.readline() '. Çıktının sınırlandırılmış olmasa da süresiz olarak engellemeye dikkat etmelisiniz. Linux I'de _think_ ile stdout borusunu bloke etmek için 'fcntl'yi kullanarak ve daha sonra erOno = EAGAIN ile IOError'ı yakalayabilirsiniz. Ex - 'fcntl.fcntl (subproc.stdout.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)' –

+0

Borunun tıkamayan okumaları hakkında referans bağlantısı - (http://www.gossamer-threads.com/lists)/python/dev/658205) –

2

Nasıl yaklaşık

 
import os, subprocess 
runcodes = ["script1.C", "script2.C"] 
ps = {} 
for script in runcodes: 
    args = ["root", "-l", "-q", script] 
    p = subprocess.Popen(args) 
    ps[p.pid] = p 
print "Waiting for %d processes..." % len(ps) 
while ps: 
    pid, status = os.wait() 
    if pid in ps: 
     del ps[pid] 
     print "Waiting for %d processes..." % len(ps) 
İlgili konular