Возможно, об этом спрашивали в аналогичном контексте, но я не смог найти ответ примерно через 20 минут поиска, поэтому спрошу.
Я написал сценарий Python (скажем: scriptA.py) и сценарий (скажем, scriptB.py)
В scriptB я хочу вызвать scriptA несколько раз с разными аргументами, каждый раз для запуска требуется около часа (это огромный сценарий, делает много всего ... не беспокойтесь об этом), и я хочу иметь возможность запускать scriptA со всеми различными аргументами одновременно, но мне нужно подождать, пока ВСЕ они не будут выполнены, прежде чем продолжить; мой код:
import subprocess
#setup
do_setup()
#run scriptA
subprocess.call(scriptA + argumentsA)
subprocess.call(scriptA + argumentsB)
subprocess.call(scriptA + argumentsC)
#finish
do_finish()
Я хочу запустить все subprocess.call()
одновременно, а затем подождать, пока все они будут выполнены, как мне это сделать?
Я пытался использовать потоки, как в примере здесь :
from threading import Thread
import subprocess
def call_script(args)
subprocess.call(args)
#run scriptA
t1 = Thread(target=call_script, args=(scriptA + argumentsA))
t2 = Thread(target=call_script, args=(scriptA + argumentsB))
t3 = Thread(target=call_script, args=(scriptA + argumentsC))
t1.start()
t2.start()
t3.start()
Но я не думаю, что это правильно.
Как я узнаю, что все они закончили бег, прежде чем идти ко мне do_finish()
?
источник
join
блокируется до тех пор, пока поток не завершит выполнение. В любом случае вам придется ждать всех потоков. Еслиt1
сначала завершится, вы начнете ждатьt2
(которое, возможно, уже закончилось, и вы немедленно перейдете к ожиданиюt3
). Если выполнениеt1
заняло больше всего времени, когда вы вернетесь из него, обаt1
иt2
сразу же вернутся без блокировки.join
вроде прикрепляет текущий процесс к потоку и ждет, пока он не будет выполнен, и если t2 завершится до t1, тогда, когда t1 будет выполнено, он проверит, выполняется ли t2, см. что это так, а затем проверьте t3..etc..etc .. и только тогда, когда все будет сделано, оно продолжится. здорово.Поместите потоки в список, а затем используйте метод Join
источник
for x in threads: x.join()
а не использовал понимание спискаВ Python3, начиная с Python 3.2, есть новый подход для достижения того же результата, который я лично предпочитаю традиционному созданию потока / запуску / присоединению, package
concurrent.futures
: https://docs.python.org/3/library/concurrent.futures .htmlИспользование
ThreadPoolExecutor
кода будет:Результат предыдущего кода выглядит примерно так:
Одним из преимуществ является то, что вы можете контролировать пропускную способность, задав максимальное количество одновременных рабочих.
источник
with
оператора выполняется, когда все задачи завершены.with
этом случае оператор работает так, как задумано. В любом случае, вы всегда можете открыть новый вопрос в SO и опубликовать свой код, чтобы мы могли помочь вам узнать, что происходит в вашем случае.concurrent.futures.wait
функцию, вы можете увидеть здесь реальный пример Официальные документы: docs.python.org/3/library/…Я предпочитаю использовать понимание списка на основе списка ввода:
источник
for t in threads:t.start()
не лучше?У вас может быть класс, похожий на приведенный ниже, из которого вы можете добавить n функций или console_scripts, которые вы хотите выполнять параллельно, и начать выполнение и дождаться завершения всех заданий.
источник
Из
threading
документации модуляИтак, чтобы поймать эти два случая, когда вы не заинтересованы в ведении списка создаваемых вами потоков:
Засим:
источник
Может быть, что-то вроде
источник
Я только что столкнулся с той же проблемой, когда мне нужно было дождаться всех потоков, которые были созданы с помощью цикла for. Я просто попробовал следующий фрагмент кода. Возможно, это не идеальное решение, но я подумал, что это будет простое решение. тестировать:
источник