Python параллельно Попен - PullRequest
       6

Python параллельно Попен

1 голос
/ 30 ноября 2011

Я ломаю голову над этим всю ночь ...

makeflags = ['--prefix=/usr','--libdir=/usr/lib']
rootdir='/tmp/project'
ps = set()

def configModule(m):
    print m
    return Popen(["./autogen.sh"] + makeflags, cwd=rootdir+"/"+m)

for module in ['mod1','mod2','mod3' ... 'mod10']:
    ps.add(configModule(module))

os.wait()

Я ожидал, что он запустит 10 процессов и будет выполнять ./autogen.sh параллельно. Однако то, что я заметил, было то, что первые несколько configModule, казалось, выходили, как только были вызваны функции. Я вижу только оператор «print m», но не фактический вывод ./autogen.sh в «mod1». Тем не менее, примерно через mod4 код начал работать параллельно. Я вижу, что загрузка ЦП высока, а выходные данные генерируются в разных папках модулей.

Есть идеи, почему первые несколько модулей не дали результата ./autogen.sh?

P.S. Если я запускаю этот код в последовательном режиме (то есть, используя subprocess.call вместо Popen), он работает правильно.

Ответы [ 2 ]

1 голос
/ 30 ноября 2011

Аналогично собранная программа с фиктивным системным вызовом работает как положено:

from subprocess import *

makeflags = ['--prefix=/usr','--libdir=/usr/lib']
rootdir='/tmp/project'
ps = dict()

def configModule(m):
    print m
    p = Popen("echo start %s; sleep %d; echo finish %s" % (m, 10-m, m), shell=True)
    #p.m = m
    return p

for module in range(10):
    ps[configModule(module)] = module

while ps:
    done = set()
    for p in ps:
        s = p.poll()
        if s is not None:
            print "Module %d: %d" % (ps[p], s)
            done.add(p)
    for p in done:
        del ps[p]
#os.wait()

Вы уверены, что вывод действительно отсутствует или просто задерживается?

КСТАТИ:

for module in ('mod%d' % i for i in range(1, 11)):

элегантнее ...

1 голос
/ 30 ноября 2011

Ваш код работает для меня, и должен запустить все процессы. Ты не даешь нам много работы: чем отличается поведение?

Вы не перенаправляете вывод в вставленном вами коде, поэтому вы, вероятно, видите потоки stderr дочерних элементов. Но есть одна вещь:

os.wait()

… будет ждать только 1 процесс. Возможно, вы захотите использовать возвращаемое значение из Popen и вызывать wait или communicate для каждого из дочерних процессов. Затем вы можете дополнительно использовать возвращаемые значения, чтобы убедиться, что все они успешно умирают:

# Instead of os.wait():
for p in ps:
    p.wait()
    print 'A process returned:', p.returncode

Надеюсь, все они должны быть равны 0, если все возвращается в порядке.

...