비슷한 맥락에서 물었을지 모르지만 약 20 분 정도 검색해도 답을 찾을 수 없어서 물어 보겠습니다.
Python 스크립트 (scriptA.py)와 스크립트 (scriptB.py)를 작성했습니다.
scriptB에서 저는 다른 인수로 scriptA를 여러 번 호출하고 싶습니다. 매번 실행하는 데 약 한 시간이 걸립니다 (대용량 스크립트이며 많은 작업을 수행합니다. 걱정하지 마십시오). 모든 다른 인수를 동시에 사용하는 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()
있습니까?
답변
스크립트의 끝에서 개체의 결합 방법 을 사용해야 Thread
합니다.
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
실행을 완료합니다.
답변
스레드를 목록에 넣은 다음 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()
답변
Python3에서는 Python 3.2부터 동일한 결과를 얻을 수있는 새로운 접근 방식이 있습니다. 저는 개인적으로 전통적인 스레드 생성 / 시작 / 조인 패키지를 선호합니다 concurrent.futures
. https://docs.python.org/3/library/concurrent.futures .html
ThreadPoolExecutor
코드를 사용하면 다음 과 같습니다.
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')
이전 코드의 출력은 다음과 같습니다.
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
장점 중 하나는 최대 동시 작업자를 설정하는 처리량을 제어 할 수 있다는 것입니다.
답변
입력 목록을 기반으로 목록 이해를 사용하는 것을 선호합니다.
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]
답변
병렬 열정으로 실행하려는 ‘n’개의 함수 또는 console_scripts를 추가하고 실행을 시작하고 모든 작업이 완료 될 때까지 기다릴 수있는 아래와 같은 클래스를 가질 수 있습니다.
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()
답변
로부터 threading
모듈 문서
“메인 스레드”개체가 있습니다. 이것은 Python 프로그램의 초기 제어 스레드에 해당합니다. 데몬 스레드가 아닙니다.
“더미 스레드 개체”가 생성 될 가능성이 있습니다. 이들은 “외계 스레드”에 해당하는 스레드 개체로, C 코드에서 직접 시작하는 것과 같이 스레딩 모듈 외부에서 시작된 제어 스레드입니다. 더미 스레드 개체는 기능이 제한되어 있습니다. 그들은 항상 살아 있고 악마적인 것으로 간주되며
join()
편집 할 수 없습니다 . 외계인 스레드의 종료를 감지 할 수 없기 때문에 절대 삭제되지 않습니다.
따라서 작성한 스레드 목록을 유지하는 데 관심이없는 두 가지 경우를 포착하려면 다음을 수행하십시오.
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]
답변
아마도
for t in threading.enumerate():
if t.daemon:
t.join()