запуск / ожидание Python на «парных» процессах параллельно (возможно, popen / wait / subprocess?) - PullRequest
0 голосов
/ 29 декабря 2018

Я вполне уверен, что некоторые функции уже существуют для этого, но я не смог найти его.То, что я в основном пытаюсь сделать, это то, что мы написали бы в BASH как:

( sleep 1; echo "one" ) &
( sleep 2; echo "two" ) &
( sleep 3; echo "three" ) &
( sleep 4; echo "four" ) &

и выполняем все это за четыре секунды (не десять секунд) ...

В более общем случае рассмотрим случай, когда у меня есть длинный список процессов, которые мне нужно запустить: (A1, B1, C1, D1 ...).У меня также есть список «парных» процессов, давайте назовем их (A2, B2, C2, D2 ...). Когда любые процессы «x1» завершатся, я хочу запустить соответствующий процесс «x2», но я хочу иметьвсе процессы x1 запускаются параллельно, и по завершении каждого из них я хочу, чтобы процесс x2 был запущен.

Я выяснил, как использовать subprocess.Popen, помещать каждый экземпляр в список и ждатьна всех тех, чтобы закончить, но я был в состоянии только ждать на всем начальном наборе, и затем запустить второй сет.Это лучше, но не идеально на любом участке.Это кажется чем-то, что не должно быть слишком ужасно сложным, но я не смог его найти.

Еще один способ подумать об этом заключается в том, что если у меня есть десять парных процессов, сразу после вызова у меня будет десять запущенных процессов и десять ДРУГИХ процессов, каждый из которых ожидает завершения одной из первых десяти.

(Это на самом деле должно решить большую, более общую проблему, но как только я смогу решить этот случай, я смогу обобщить и масштабировать его ...)

1 Ответ

0 голосов
/ 29 декабря 2018

Вы можете решить эту проблему в Python разными способами.Вот три очевидных:

  • Так же, как оболочка решает это.Это, вероятно, самый простой способ, по крайней мере, в Unix-подобной системе, но он обеспечивает некоторое разделение, которое вам может не понадобиться, и не работает в Windows.
  • Через опрос.Если вам нечего делать во время опроса, это может быть пустой тратой системных ресурсов.
  • Через многопоточность.Это самый легкий вес, но и самый хитрый, чтобы получить право.

Способ, которым оболочка справляется с этим, заключается в том, что:

( sleep 1; echo "one" ) &

разветвляется на подоболочку.Суб-оболочка разветвляется на суб-суб-оболочку, а суб-суб-оболочка exec s - sleep 1.Первая вложенная оболочка теперь ожидает вторую вложенную оболочку, а когда она заканчивается, исполняется (на этот раз не требуется разветвление) echo "one".(Между тем основная оболочка вообще не ждет.)

Обратите внимание, что число процессов здесь было 3: основная оболочка, суб-оболочка, суб-суб-оболочка, которая стала первым эхом, изатем первый субоболочка стал вторым эхом.Основная оболочка может ожидать и, следовательно, получить статус результата первой вложенной оболочки, но она вообще не может видеть вложенную оболочку.

Чтобы сделать это непосредственно в Python, либо вызовитеоболочка для последовательного запуска двух команд - эта оболочка разветвляется один раз для первой команды, затем запускает вторую напрямую или использует os.fork().Если вы - потомок вилки, используйте subprocess.call или .Popen или любым другим) для запуска первой команды, затем используйте os.exec для запуска второй команды.В качестве альтернативы, вы можете добавить еще больше процессов и / или использовать multiprocessing (который добавляет необычный механизм связи между вашими различными процессами Python, так что вы можете делать гораздо больше полезных вещей, но он еще тяжелее).

Чтобы использовать опрос, обратите внимание, что экземпляр subprocess.Popen имеет метод poll.Вызовите это, чтобы узнать, запущен ли процесс или уже завершен.

Чтобы использовать многопоточность, раскрутите потоки, которые вызывают subprocess.Popen и / или которые вызывают метод .wait в созданном подпроцессе, а затем вращайтедо следующего в цепи.Вам нужно будет добавить свою собственную блокировку вокруг любых переменных, совместно используемых различными потоками (например, различными рабочими списками) - может иметь смысл разделить их перед тем, как раскрутить потоки, чтобы у каждого потока был собственный рабочий список.и просто вносит окончательные результаты, если таковые имеются, под замком).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...