Запустите все приложение Twisted в нескольких процессах

Я знаю об ограничениях Twisted для многопроцессорных приложений, но мой вопрос в другом. Я не пытаюсь запустить сервер или клиент, используя несколько процессов. У меня уже есть запущенное приложение, которое берет несколько каталогов и выполняет над ними некоторые операции. Я хочу разделить работу на куски, порождая процесс с одним и тем же приложением для каждого подкаталога. Я могу сделать это, запуская приложение несколько раз из оболочки и каждый раз передавая в качестве аргумента другой подкаталог.

В основном у меня есть что-то вроде:

from multiprocessing import Pool
...
p = Pool(num_procs)
work_chunks = [work_chunk] * len(configs)
p.map(run_work_chunk, zip(work_chunks, configs))
p.close()
p.join()

где:

def run_work_chunk((work_chunk, config)):
    from twisted.internet import reactor
    d = work_chunk.configure(config)

    d.addCallback(lambda _: work_chunk.run())
    d.addErrback(handleLog)
    print "pid=", getpid(), "reactor=", id(reactor)
    reactor.run()
    return

class WorkChunk(object):
    ...
    def run(self):
        # do stuff
        ...
        reactor.stop()

Допустим, num_procs равно 2, тогда вывод будет примерно таким:

pid=2 реактор=140612692700304

pid=6 реактор=140612692700304

И вы не можете видеть никаких результатов для рабочих, работающих в других фрагментах.

Проблема в том, что когда вызывается reactor.stop(), он останавливает все реакторы, потому что каждый процесс использует один и тот же реактор. Я думал, что при порождении нового процесса копируется весь стек, но в данном случае копируется ссылка на реактор, поэтому все процессы используют один и тот же объект реактора.

Есть ли способ создать экземпляр другого объекта реактора для каждого процесса? (как будто это действительно был совсем другой процесс, а не дочерний процесс)


person synack    schedule 04.06.2015    source источник


Ответы (1)


Есть ли способ создать экземпляр другого объекта реактора для каждого процесса? (как будто это действительно был совсем другой процесс, а не дочерний процесс)

Если вы действительно имеете в виду process, то лучший способ - запустить код несколько раз (и/или fork/exec для создания новых процессов из вашего исходного процесса).

В управлении несколькими реакторами нет никакой магии, это делается так же, как вы запускаете несколько программ в любом другом контексте.

person Mike Lutz    schedule 04.06.2015
comment
Спасибо за ответ. Разве это не то, что я делаю в источнике моего вопроса? В Unix модуль многопроцессорности разветвляется для создания новых процессов. Вопрос в том, что, несмотря на то, что я разветвляюсь, объект реактора распределяется между разветвленными процессами... - person synack; 04.06.2015
comment
@mjm: я не работал с многопроцессорной библиотекой python, поэтому я согласен, судя по ее документам, что она должна делать что-то вроде того, о чем я говорю, но взгляните на SO: - person Mike Lutz; 04.06.2015
comment
И см.: stackoverflow .com/questions/11272874/ . Я думаю, это может объяснить проблему, которую вы видите (особенно, когда Жан-Поль говорит о проблеме с запуском exec()) - person Mike Lutz; 04.06.2015
comment
Спасибо за ссылки. Я их уже читал. Это то, что я имел в виду под I know about the limitations of Twisted for multiprocess applications. Моя проблема в том, что я вообще не использую многопроцессорность для внутренностей скрученного приложения. Я использую многопроцессорность для создания приложения в целом в другом процессе.... - person synack; 04.06.2015
comment
Если ваш код (напрямую или через библиотеку) exec искажает код, все должно быть в порядке. Если нет, как объяснил Жан-Поль, вы в мире опасного общего состояния. К вашему сведению: если вы просмотрели другие SO, чтобы задать свой вопрос, это сэкономит время ответа, если вы укажете их в своем вопросе. - person Mike Lutz; 04.06.2015