Dies wurde möglicherweise in einem ähnlichen Zusammenhang erfragt, aber nach etwa 20 Minuten Suche konnte ich keine Antwort finden, daher werde ich fragen.
Ich habe ein Python-Skript (sagen wir: scriptA.py) und ein Skript (sagen wir scriptB.py) geschrieben.
In scriptB möchte ich scriptA mehrmals mit verschiedenen Argumenten aufrufen, jedes Mal dauert es etwa eine Stunde, um ausgeführt zu werden (es ist ein riesiges Skript, das eine Menge Sachen erledigt.. scriptA mit allen verschiedenen Argumenten gleichzeitig, aber ich muss warten, bis ALLE von ihnen fertig sind, bevor ich fortfahre; mein code:
import subprocess
#setup
do_setup()
#run scriptA
subprocess.call(scriptA + argumentsA)
subprocess.call(scriptA + argumentsB)
subprocess.call(scriptA + argumentsC)
#finish
do_finish()
Ich möchte alle subprocess.call()
gleichzeitig ausführen und dann warten, bis alle fertig sind. Wie soll ich das tun?
Ich habe versucht, Threading wie im Beispiel hier zu verwenden:
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()
Aber ich denke nicht, dass das richtig ist.
Woher weiß ich, dass alle mit dem Laufen fertig sind, bevor ich zu meiner do_finish()
gehe?
Sie müssen am Ende des Skripts join der Methode Thread
verwenden.
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()
Daher wartet der Haupt-Thread, bis t1
, t2
und t3
die Ausführung beenden.
Füge die Threads in eine Liste ein und verwende dann die Join-Methode
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()
Ich bevorzuge das Listenverständnis basierend auf einer Eingabeliste:
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]
In Python3 gibt es seit Python 3.2 einen neuen Ansatz, um das gleiche Ergebnis zu erzielen, das ich persönlich der traditionellen Thread-Erstellung/Start/Join-Paket concurrent.futures
: https://docs.python.org/3/library) bevorzuge /concurrent.futures.html
Bei Verwendung einer ThreadPoolExecutor
lautet der Code:
from concurrent.futures.thread import ThreadPoolExecutor
import time
def call_script(ordinal, arg):
print('Thread', ordinal, 'argument:', arg)
time.sleep(2)
print('Thread', ordinal, 'Finished')
args = ['argumentsA', 'argumentsB', 'argumentsC']
with ThreadPoolExecutor(max_workers=2) as executor:
ordinal = 1
for arg in args:
executor.submit(call_script, ordinal, arg)
ordinal += 1
print('All tasks has been finished')
Die Ausgabe des vorherigen Codes ist ungefähr so:
Thread 1 argument: argumentsA
Thread 2 argument: argumentsB
Thread 1 Finished
Thread 2 Finished
Thread 3 argument: argumentsC
Thread 3 Finished
All tasks has been finished
Einer der Vorteile ist, dass Sie den Durchsatz einstellen können, indem Sie die maximale Anzahl gleichzeitiger Mitarbeiter einstellen.
Sie können über eine Klasse wie unten verfügen, aus der Sie 'n' Anzahl von Funktionen oder console_scripts hinzufügen können, die Sie parallel ausführen möchten, die Ausführung starten und warten, bis alle Jobs abgeschlossen sind.
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 __== '__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()
Vielleicht so etwas
for t in threading.enumerate():
if t.daemon:
t.join()
Aus der threading
Moduldokumentation
Es gibt ein "Hauptthread" -Objekt. das entspricht dem ersten Thread der Steuerung im Python-Programm. Es ist kein Daemon-Thread.
Es besteht die Möglichkeit, dass "Dummy-Thread-Objekte" erstellt werden . Dies sind Thread-Objekte, die "Alien-Threads" entsprechen. Dies sind Kontrollthreads, die außerhalb des Threading-Moduls gestartet wurden, z. B. direkt aus C-Code. Dummy-Thread-Objekte haben eine eingeschränkte Funktionalität; Sie gelten immer als lebendig und daemonisch und können nicht
join()
ed . Sie werden niemals gelöscht, da es nicht möglich ist, das .__ zu erkennen. Terminierung von außerirdischen Threads.
Um diese beiden Fälle zu erfassen, wenn Sie nicht daran interessiert sind, eine Liste der von Ihnen erstellten Threads zu führen:
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
Worauf:
>>> print(data)
[0, 4, 12, 40]
Ich bin gerade auf das gleiche Problem gestoßen, wo ich auf alle Threads warten musste, die mit der for-Schleife erstellt wurden. Ich habe gerade den folgenden Code ausprobiert. Vielleicht ist es nicht die perfekte Lösung, aber ich dachte, es wäre eine einfache Lösung zu testen:
for t in threading.enumerate():
try:
t.join()
except RuntimeError as err:
if 'cannot join current thread' in err:
continue
else:
raise