복붙노트

[PYTHON] 모든 스레드가 완료 될 때까지 파이썬 다중 스레드 대기

PYTHON

모든 스레드가 완료 될 때까지 파이썬 다중 스레드 대기

이것은 비슷한 맥락에서 질문을 받았을 지 모르지만 약 20 분의 검색 후에 답을 찾을 수 없었기 때문에 물어볼 것입니다.

Python 스크립트 (scriptA.py라고 말하면 됨)와 스크립트 (scriptB.py라고 말하면 됨)를 작성했습니다.

scriptB에서 나는 scriptA를 여러 인자로 여러 번 호출하기를 원할 때마다 매 시간마다 실행하는데 약 1 시간이 걸린다. (거대한 스크립트는 많은 것을 처리한다. 걱정하지 마라.) 나는 그 스크립트를 실행할 수 있기를 원한다. scriptA는 동시에 모든 다른 인수를 가지고 있지만, 계속하기 전에 모든 것이 완료 될 때까지 기다려야합니다. 내 코드 :

import subprocess

#setup
do_setup()

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

#finish
do_finish()

같은 시간에 모든 subprocess.call ()을 실행하고 모두 완료 될 때까지 기다렸다가 어떻게해야합니까?

여기 예제와 같은 스레딩을 사용하려고했습니다.

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

그러나 나는 이것이 옳다고 생각하지 않는다.

do_finish ()에 가기 전에 모두 실행이 끝났음을 어떻게 알 수 있습니까?

해결법

  1. ==============================

    1.스크립트 끝에서 Thread 객체의 join 메소드를 사용해야한다.

    스크립트 끝에서 Thread 객체의 join 메소드를 사용해야한다.

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

    따라서 주 스레드는 t1, t2 및 t3이 끝날 때까지 대기합니다.

  2. ==============================

    2.스레드를 목록에 넣고 Join 메서드를 사용하십시오.

    스레드를 목록에 넣고 Join 메서드를 사용하십시오.

     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()
    
  3. ==============================

    3.입력 목록을 기반으로하는 목록 이해력을 선호합니다.

    입력 목록을 기반으로하는 목록 이해력을 선호합니다.

    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]
    
  4. ==============================

    4.파이썬 3에서는 파이썬 3.2부터 동일한 결과에 도달하기위한 새로운 접근법이 있습니다. 개인적으로 전통적인 스레드 생성 / 시작 / 결합, concurrent.futures 패키지를 선호합니다 : https://docs.python.org/3/library/ concurrent.futures.html

    파이썬 3에서는 파이썬 3.2부터 동일한 결과에 도달하기위한 새로운 접근법이 있습니다. 개인적으로 전통적인 스레드 생성 / 시작 / 결합, concurrent.futures 패키지를 선호합니다 : https://docs.python.org/3/library/ concurrent.futures.html

    ThreadPoolExecutor를 사용하면 코드는 다음과 같습니다.

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

    장점 중 하나는 최대 동시 작업자 수를 설정하는 처리량을 제어 할 수 있다는 것입니다.

  5. ==============================

    5.아래 열거 된 것과 같은 클래스를 사용하여 병렬 함수로 실행할 함수 또는 console_script를 추가하고 실행을 시작한 다음 모든 작업이 완료 될 때까지 기다릴 수 있습니다.

    아래 열거 된 것과 같은 클래스를 사용하여 병렬 함수로 실행할 함수 또는 console_script를 추가하고 실행을 시작한 다음 모든 작업이 완료 될 때까지 기다릴 수 있습니다.

    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()
    
  6. ==============================

    6.어쩌면, 뭔가

    어쩌면, 뭔가

    for t in threading.enumerate():
        if t.daemon:
            t.join()
    
  7. ==============================

    7.난 그냥 for 루프를 사용하여 만든 모든 스레드를 기다릴 필요가 같은 문제가 왔어. 난 그냥 다음 코드 조각을 시도했다. 그것은 완벽한 솔루션이되지 않을 수도 있지만 간단한 해결책이 될 것이라고 생각 테스트하기 :

    난 그냥 for 루프를 사용하여 만든 모든 스레드를 기다릴 필요가 같은 문제가 왔어. 난 그냥 다음 코드 조각을 시도했다. 그것은 완벽한 솔루션이되지 않을 수도 있지만 간단한 해결책이 될 것이라고 생각 테스트하기 :

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

    8.스레딩 모듈 문서에서

    스레딩 모듈 문서에서

    따라서 작성한 스레드 목록을 유지하는 데 관심이없는 경우 두 가지 경우를 포착하십시오.

    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
    

    그래서:

    >>> print(data)
    [0, 4, 12, 40]
    
  9. from https://stackoverflow.com/questions/11968689/python-multithreading-wait-till-all-threads-finished by cc-by-sa and MIT license