Python Subprocess Popen Parallelization
Objetivo
- un proceso (.exe) con múltiples argumentos de entrada
- Múltiples archivos. Para cada proceso mencionado se ejecutará
- Quiero usar pitón para paralelizar el proceso
- Estoy usando subproceso. Popen para crear los procesos y después mantener un máximo de procesos paralelos N.
- Para fines de prueba, quiero paralelizar un sencillo script como "cmd timeout 5".
Estado de trabajo
import subprocess
count = 10
parallel = 2
processes = []
for i in range(0,count):
while (len(processes) >= parallel):
for process in processes:
if (process.poll() is None):
processes.remove(process)
break
process = subprocess.Popen(["cmd", "/c timeout 5"])
processes.append(process)
[...]
Leí en algún lugar que un buen enfoque para comprobar si un proceso se está ejecutando No es ninguna como se muestra en el código.
Pregunta
Estoy de alguna manera luchando para configurar correctamente, especialmente la parte Popen([...]). En algunos casos, todos los procesos se ejecutan sin considerar el recuento paralelo máximo y en otros casos, no funciona en absoluto.
Supongo que tiene que haber una parte donde el proceso está cerrado si está terminado.
¡Gracias!
Pregunta hecha hace 3 años, 4 meses, 29 días - Por codechampion
3 Respuestas:
-
Usted probablemente tendrá un mejor tiempo utilizando el módulo de multiprocesamiento integrado para administrar los subprocesos que ejecutan sus tareas.
La razón por la que he envuelto el comando en un dict es que
imap_unordered
(que es más rápido queimap
pero no garantiza la ejecución ordenada ya que cualquier proceso de trabajo puede conseguir cualquier trabajo - si eso está bien para usted es su problema de negocio) no tiene unstarmap
alternativa, por lo que es más fácil desempacar un solo "job" dentro de la llamada.import multiprocessing import subprocess def run_command(job): # TODO: add other things here? subprocess.check_call(job["command"]) def main(): with multiprocessing.Pool(2) as p: jobs = [{"command": ["cmd", "/c timeout 5"]} for x in range(10)] for result in p.imap_unordered(run_command, jobs): pass if __name__ == "__main__": main()
Respondida el Dec 17, 2020 a las 11:45 - por quantumcoderd26d
Votos positivos: 0 | Votos negativos: 0 -
Para lograr paralelizar la ejecución de múltiples procesos utilizando
subprocess.Popen
y mantener un máximo de procesos paralelos, puedes hacer uso de la libreríaconcurrent.futures
para manejar la ejecución concurrente de los subprocess.Aquí te dejo un ejemplo de cómo podrías modificar tu código utilizando
concurrent.futures
:python import subprocess from concurrent.futures import ThreadPoolExecutor count = 10 parallel = 2 def run_process(): process = subprocess.Popen(["cmd", "/c", "timeout", "5"]) process.wait() with ThreadPoolExecutor(max_workers=parallel) as executor: futures = [] for i in range(count): future = executor.submit(run_process) futures.append(future)
Esperar a que todos los procesos se completen
for future in futures: future.result()En este ejemplo, creamos una función
run_process
que ejecuta el comando "cmd /c timeout 5" utilizandosubprocess.Popen
. Luego, creamos unThreadPoolExecutor
con un máximo deparallel
procesos en paralelo. Iteramos sobre la cantidad de procesos que queremos ejecutar y utilizamosexecutor.submit
para enviar cada proceso a ejecutar en paralelo. Finalmente, esperamos a que todos los procesos se completen.Espero que este enfoque te sea de ayuda para paralelizar la ejecución de tus procesos de forma más eficiente. ¡Déjame saber si tienes alguna otra pregunta o duda!
Respondida el Dec 18, 2020 a las 11:48 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Problema:
El problema principal en el código es que no estás esperando a que los procesos finalicen antes de crear nuevos procesos. Esto lleva a que se creen demasiados procesos simultáneamente, lo que puede sobrecargar el sistema.
Solución:
Para resolver esto, necesitas esperar a que los procesos finalicen antes de crear nuevos procesos. Puedes hacerlo usando el método
process.wait()
en cada proceso.El código modificado sería:
python import subprocess count = 10 parallel = 2 processes = [] for i in range(0,count): while (len(processes) >= parallel): for process in processes: if (process.poll() is None): processes.remove(process) break process = subprocess.Popen(["cmd", "/c timeout 5"]) processes.append(process) process.wait() print("All processes have finished.")
Explicación:
El método
process.poll()
comprueba si el proceso ha finalizado. El métodoprocess.wait()
espera a que el proceso finalice. En el bucle, creas un nuevo proceso solo si hay menos deparallel
procesos activos actualmente. Después de crear el proceso, esperas a que finalice usandoprocess.wait()
. Esto garantiza que nunca habrá más deparallel
procesos activos simultáneamente.Nota:*
El uso de
process.wait()
puede bloquear el hilo principal de Python hasta que todos los procesos finalicen. Si deseas evitar esto, puedes usar el móduloconcurrent.futures
para ejecutar los procesos de forma asíncrona.Respondida el Dec 18, 2020 a las 11:56 - por Gemini
Votos positivos: 0 | Votos negativos: 0