Esto puede haber sido formuladas en un contexto similar, pero no pude encontrar una respuesta después de unos 20 minutos de búsqueda, así que voy a preguntar.

He escrito un script de Python (digamos: scriptA.py) y una secuencia de comandos (digamos scriptB.py)

En scriptB quiero llamar scriptA varias veces con diferentes argumentos, cada vez que toma alrededor de una hora para ejecutar, (es un gran script, hace un montón de cosas.. no te preocupes) y quiero ser capaz de ejecutar la scriptA con todos los argumentos diferentes al mismo tiempo, pero tengo que esperar hasta que TODOS ellos se hacen antes de continuar; mi código:

import subprocess

#setup
do_setup()

#run scriptA
subprocess.call(scriptA + argumentsA)
subprocess.call(scriptA + argumentsB)
subprocess.call(scriptA + argumentsC)

#finish
do_finish()

Quiero hacer ejecutar todos los subprocess.call() al mismo tiempo, y luego esperar hasta que todos se hacen, ¿cómo debo hacerlo?

He intentado utilizar el roscado, como el ejemplo que aquí:

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()

Pero no creo que esto es correcto.

¿Cómo sé que todos ellos han terminado de ejecutarse antes de ir a mi do_finish()?

OriginalEl autor Inbar Rose | 2012-08-15

8 Comentarios

  1. 106

    Necesita utilizar únete método de Thread objeto en el final de la secuencia de comandos.

    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()
    
    t1.join()
    t2.join()
    t3.join()

    Por lo tanto el hilo principal esperar hasta t1, t2 y t3 finalizar la ejecución.

    hmmm – teniendo problemas para entender algo, no se esta primera ejecución t1, espere hasta que su acabado, a continuación, ir a la t2..etc,etc ? ¿cómo hacer que todo suceda a la vez? yo no veo cómo esto podría ejecutar en el mismo tiempo?
    La llamada a join se bloquea hasta que el hilo finaliza la ejecución. Usted tendrá que esperar a que todos los hilos de todos modos. Si t1 acabados de primera comenzará esperando en t2 (que podría ser ya terminado y se procederá inmediatamente a esperar para t3). Si t1 tardó en ejecutar, cuando regrese de tanto t1 y t2 volverá inmediatamente sin el bloqueo.
    usted no entiende mi pregunta – si puedo copiar el código anterior a mi código funciona? o me estoy perdiendo algo?
    lo siento, se me ha perdido la parte que realmente empieza hilos de ejecución (actualizado la respuesta). Sí, el código, como es ahora, va a funcionar como se espera.
    bueno, veo. ahora entiendo, estaba un poco confundido acerca de ella, pero yo creo entender, join tipo de adjunta el proceso actual para el hilo y espera hasta que su hecho, y si t2 termina antes de t1 entonces cuando t1 es el hecho de que se compruebe t2 está haciendo ver que es, y, a continuación, compruebe t3..etc..etc.. y, a continuación, sólo cuando se hace esto continuará. impresionante.

    OriginalEl autor Maksim Skurydzin

  2. 128

    Poner los hilos en una lista y, a continuación, utilizar la Método de combinación

     threads = []
    
     t = Thread(...)
     threads.append(t)
    
     ...repeat as often as necessary...
    
     # Start all threads
     for x in threads:
         x.start()
    
     # Wait for all of them to finish
     for x in threads:
         x.join()
    Sí, eso iba a funcionar, pero es más difícil de entender. Usted siempre debe tratar de encontrar un equilibrio entre el compacto de código y «legibilidad». Recuerde: el Código está escrito de una vez y leer muchas veces. Por lo que es más importante, que es fácil de entender.
    El «patrón de fábrica» es algo que no puedo explicar en una sola frase. Google y search stackoverflow.com. Hay muchos ejemplos y explicaciones. En pocas palabras: escribir el código que construye algo complejo para usted. Como una verdadera fábrica: Se dan en un orden y obtener un producto terminado.
    No me gusta la idea de utilizar la lista de comprensión, los efectos secundarios y no hacer nada útil con el resultado de la lista. Un simple bucle for estaría más limpio, incluso si se extiende dos filas…
    DIgull entiendo que.Lo que quiero decir es que me acaba de hacer un for x in threads: x.join() en lugar de utilizar la lista de comprehantion
    Todavía me pregunto si hay una forma más legible y eficiente solución: stackoverflow.com/questions/21428602/…

    OriginalEl autor Aaron Digulla

  3. 18

    Yo prefiero usar la lista de comprensión basado en una lista de entrada:

    inputs = [scriptA + argumentsA, scriptA + argumentsB, ...]
    threads = [Thread(target=call_script, args=(i)) for i in inputs]
    [t.start() for t in threads]
    [t.join() for t in threads]
    Comprueba respuesta explica bien, pero este es más corto y no requiere feo repeticiones. Sólo una buena respuesta. 🙂
    La comprensión de listas sólo para efectos secundarios generalmente se amortizan*. Pero en este caso de uso, parece ser una buena idea. *stackoverflow.com/questions/5753597/…
    for t in threads:t.start() , ¿no es mejor?

    OriginalEl autor Adam Matan

  4. 13

    En Python3, dado que Python 3.2 no es un nuevo enfoque para alcanzar el mismo resultado, que yo, personalmente, prefiero a la tradicional rosca de creación/inicio/join, paquete concurrent.futures: https://docs.python.org/3/library/concurrent.futures.html

    El uso de un ThreadPoolExecutor el código sería el siguiente:

    from concurrent.futures.thread import ThreadPoolExecutor
    
    def call_script(arg)
        subprocess.call(scriptA + arg)
    
    args = [argumentsA, argumentsB, argumentsC]
    with ThreadPoolExecutor(max_workers=2) as executor:
        for arg in args:
            executor.submit(call_script, arg)
    print('All tasks has been finished')

    Una de las ventajas es que se puede controlar el rendimiento de la configuración de la max concurrente de los trabajadores.

    pero, ¿cómo puede usted decir cuando todos los subprocesos del grupo de subprocesos han terminado?
    Como se puede ver en el ejemplo, el código después de la with instrucción se ejecuta cuando todas las tareas se han terminado.

    OriginalEl autor Roberto

  5. 5

    Usted puede tener la clase de algo, como a continuación a partir de la cual puede añadir ‘n’ número de funciones o console_scripts desea ejecutar en paralelo la pasión y el inicio de la ejecución y espere a que todos los trabajos para completar..

    from multiprocessing import Process
    
    class ProcessParallel(object):
        """
        To Process the  functions parallely
    
        """    
        def __init__(self, *jobs):
            """
            """
            self.jobs = jobs
            self.processes = []
    
        def fork_processes(self):
            """
            Creates the process objects for given function deligates
            """
            for job in self.jobs:
                proc  = Process(target=job)
                self.processes.append(proc)
    
        def start_all(self):
            """
            Starts the functions process all together.
            """
            for proc in self.processes:
                proc.start()
    
        def join_all(self):
            """
            Waits untill all the functions executed.
            """
            for proc in self.processes:
                proc.join()
    
    
    def two_sum(a=2, b=2):
        return a + b
    
    def multiply(a=2, b=2):
        return a * b
    
    
    #How to run:
    if __name__ == '__main__':
        #note: two_sum, multiply can be replace with any python console scripts which
        #you wanted to run parallel..
        procs =  ProcessParallel(two_sum, multiply)
        #Add all the process in list
        procs.fork_processes()
        #starts  process execution 
        procs.start_all()
        #wait until all the process got executed
        procs.join_all()

    OriginalEl autor PBD

  6. 2

    Tal vez, algo así como

    for t in threading.enumerate():
        if t.daemon:
            t.join()
    He probado este código, pero no estás seguro acerca de su trabajo debido a que la última instrucción de mi código impreso que fue después de este bucle for y todavía el proceso no fue terminado.
    tal vez no todos los hilos eran demonios?

    OriginalEl autor jno

  7. 0

    Me encontré con el mismo problema en el que tuve que esperar para que todos los hilos que se han creado utilizando el bucle for.Acabo de probar el siguiente fragmento de código.No puede ser la solución perfecta, pero pensé que sería una solución sencilla para la prueba:

    for t in threading.enumerate():
        try:
            t.join()
        except RuntimeError as err:
            if 'cannot join current thread' in err:
                continue
            else:
                raise

    OriginalEl autor Omkar

  8. 0

    De la threading documentación del módulo

    Hay un «hilo principal» objeto; esto corresponde a la inicial
    subproceso de control en el programa de Python. No es un demonio hilo.

    Existe la posibilidad de que «dummy hilo de objetos» son creadas.
    Estos son de hilo objetos correspondientes a «alien hilos», que son
    hilos de control iniciada fuera del roscado del módulo, tales como
    directamente desde código C. Maniquí de hilo objetos tienen una funcionalidad limitada;
    siempre se considera vivo y demoníacos, y no puede ser join()ed.
    Nunca se eliminan, ya que es imposible detectar el
    la terminación de alien hilos.

    Así, para la captura de los dos casos cuando usted no está interesado en mantener una lista de los hilos de crear:

    import threading as thrd
    
    
    def alter_data(data, index):
        data[index] *= 2
    
    
    data = [0, 2, 6, 20]
    
    for i, value in enumerate(data):
        thrd.Thread(target=alter_data, args=[data, i]).start()
    
    for thread in thrd.enumerate():
        if thread.daemon:
            continue
        try:
            thread.join()
        except RuntimeError as err:
            if 'cannot join current thread' in err.args[0]:
                # catchs main thread
                continue
            else:
                raise

    Con lo cual:

    >>> print(data)
    [0, 4, 12, 40]

    OriginalEl autor berna1111

Dejar respuesta

Please enter your comment!
Please enter your name here