threading.enumerate
дает вам список всех запущенных потоков, включая основной, так что вы можете сделать это:
main_thread = threading.main_thread()
while True:
L = threading.enumerate()
L.remove(main_thread) # or avoid it in the for loop
for t in L:
t.join()
while True
необходим в том случае, если ваша библиотека создает новые потоки, пока вы ожидаете завершения текущих.
Предполагая, что никакие потоки не создаются во время работы enumerate
, вы можете проверить, имеет ли L
только один элемент (основной поток), и если это так, разорвать цикл. В сочетании с предложением Тадхга Макдональда-Дженсена об использовании iter
со стражем, получаем:
main_thread = threading.main_thread()
main_threads = [main_thread, ] # WARN: can't have more than one thread here
for threads in iter(threading.enumerate, main_threads):
for t in threads:
if t == main_thread:
continue
t.join()
enumerate
возвращает список в неопределенном порядке, поэтому, если у вас более одного «основного» потока, порядок начинает иметь значение. Решением будет использование наборов , то есть main_threads = {main_thread, }
и iter(lambda : set(threading.enumerate()), main_threads)
.
Если вы предпочитаете EAFP подход просить прощения вместо разрешения, и все ваши потоки запускаются, когда вы достигаете конца вашего сценария, вы также можете сделать это:
for thread in threading.enumerate():
try:
thread.join()
except RuntimeError:
# trying to join the main thread, which would create a deadlock (see https://docs.python.org/3/library/threading.html#threading.Thread.join for details)
pass