Existe uma maneira de esperar por outro script Python chamado a partir do script atual (usando subprocess.Propen ()) até sua conclusão?
Estou tentando executar 2 scripts python (digamos dp_01.py e dp_02.py) a partir de um script python mestre. Eu quero executá-los um após o outro. Este é o meu código atual em script python mestre
job1_exec = "python dp_01.py"
try:
#os.system(job1_exec)
command1 = subprocess.Popen(job1_exec, shell=True)
command1.wait()
except:
print("processing of dp_01 code failed")
print("Processing of dp_01 code completed")
job2_exec = "python dp_02.py"
try:
#os.system(job2_exec)
command2 = subprocess.Popen(job2_exec, shell=True)
command2.wait()
except:
print("processing of dp_02 code failed")
print("Processing of dp_02 code completed")
O problema aqui é que o script mestre não está esperando que dp_01.py conclua sua execução. Ele imediatamente começa a executar dp_02.py. Como esperar a execução de dp_01.py ser concluída antes de iniciar a execução de dp_02.py?
Respostas
Uma solução pode ser substituir Popenpor check_outputou run. check_outputé um wrapper runque preserva e retorna o subprocesso ' stdout, e também bloqueia a thread principal durante a execução.
De acordo com esta pergunta do SO ,
A principal diferença [entre 'run' e 'Popen'] é que subprocess.run executa um comando e espera que ele termine, enquanto com subprocess.Popen você pode continuar fazendo suas coisas enquanto o processo termina e então chamar o subprocesso repetidamente. comunique-se para repassar e receber dados para o seu processo.
Vamos considerar dois trabalhos diferentes onde o número 1 leva consideravelmente mais tempo para ser executado do que o trabalho número 2, simulado aqui por um sleep(7)
# dp_01.py
import time
time.sleep(7)
print("--> Hello from dp_01", end="")
e,
# dp_02.py
print("--> Hello from dp_02", end="")
Em seguida, para a simplicidade do teste, movo o desempenho do trabalho do script principal para funções,
import time
import subprocess
jobs = ["dp_01.py", "dp_02.py"]
# The current approach of the OP, using 'Popen':
def do(job):
subprocess.Popen("python "+job, shell=True)
# Alternative, main-thread-blocking approach,
def block_and_do(job):
out = subprocess.check_output("python "+job, shell=True)
print(out.decode('ascii')) # 'out' is a byte string
# Helper function for testing the synchronization
# of the two different job-workers above
def test_sync_of_function(worker_func, jobs):
test_started = time.time()
for job in jobs:
print("started job '%s', at time %d" % (job, time.time() - test_started))
worker_func(job)
print("completed job '%s', at time %d" % (job, time.time() - test_started))
time.sleep(1)
Isto resulta em:
test_sync_of(do, jobs)
starting job 'dp_01.py', at time 0
completed job 'dp_01.py', at time 0
starting job 'dp_02.py', at time 1
completed job 'dp_02.py', at time 1
--> Hello from dp_02 !
--> Hello from dp_01 !
enquanto,
test_sync_of(block_and_do, jobs)
starting job 'dp_01.py', at time 0
--> Hello from dp_01 !
completed job 'dp_01.py', at time 7
starting job 'dp_02.py', at time 8
--> Hello from dp_02 !
completed job 'dp_02.py', at time 8
Finalmente, espero que isso resolva seu problema. No entanto, esta pode não ser a melhor solução para o seu grande problema? Você pode querer dar uma olhada no multiprocessingmódulo. Talvez seus trabalhos nos scripts separados possam ser importados como módulos e seu trabalho encadeado?
Uma nota final: você deve ter muito cuidado ao usar shell=True: consulte esta outra pergunta do SO para obter detalhes.