IT

파이썬의 스레드에서 반환 값을 얻는 방법은 무엇입니까?

lottoking 2020. 3. 25. 08:34
반응형

파이썬의 스레드에서 반환 값을 얻는 방법은 무엇입니까?


함수 foo반환 아래 문자열 'foo'. 'foo'스레드 대상에서 반환되는 어떻게 얻을 수 있습니까?

from threading import Thread

def foo(bar):
    print('hello {}'.format(bar))
    return 'foo'

thread = Thread(target=foo, args=('world!',))
thread.start()
return_value = thread.join()

: 위의 "그것을 할 수있는 하나의 확실한 방법은"작동하지 않습니다 thread.join()반환 None.


FWIW, multiprocessing모듈은 Pool클래스를 사용하여 멋진 인터페이스를 제공합니다 . 프로세스가 아닌 스레드를 고수하려면 multiprocessing.pool.ThreadPool클래스를 드롭 인 대체로 사용할 수 있습니다 .

def foo(bar, baz):
  print 'hello {0}'.format(bar)
  return 'foo' + baz

from multiprocessing.pool import ThreadPool
pool = ThreadPool(processes=1)

async_result = pool.apply_async(foo, ('world', 'foo')) # tuple of args for foo

# do some other stuff in the main process

return_val = async_result.get()  # get the return value from your function.

내가 본 한 가지 방법은 목록이나 사전과 같은 가변 객체를 인덱스 또는 일종의 다른 식별자와 함께 스레드의 생성자에 전달하는 것입니다. 그런 다음 스레드는 결과를 해당 객체의 전용 슬롯에 저장할 수 있습니다. 예를 들면 다음과 같습니다.

def foo(bar, result, index):
    print 'hello {0}'.format(bar)
    result[index] = "foo"

from threading import Thread

threads = [None] * 10
results = [None] * 10

for i in range(len(threads)):
    threads[i] = Thread(target=foo, args=('world!', results, i))
    threads[i].start()

# do some other stuff

for i in range(len(threads)):
    threads[i].join()

print " ".join(results)  # what sound does a metasyntactic locomotive make?

join()호출 된 함수의 리턴 값 을 실제로 리턴 Thread하려면 다음과 같은 서브 클래스로 이를 수행 할 수 있습니다 .

from threading import Thread

def foo(bar):
    print 'hello {0}'.format(bar)
    return "foo"

class ThreadWithReturnValue(Thread):
    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs={}, Verbose=None):
        Thread.__init__(self, group, target, name, args, kwargs, Verbose)
        self._return = None
    def run(self):
        if self._Thread__target is not None:
            self._return = self._Thread__target(*self._Thread__args,
                                                **self._Thread__kwargs)
    def join(self):
        Thread.join(self)
        return self._return

twrv = ThreadWithReturnValue(target=foo, args=('world!',))

twrv.start()
print twrv.join()   # prints foo

이름 맹 글링으로 인해 약간 털이 나오고 Thread구현 과 관련된 "개인"데이터 구조에 액세스 하지만 작동합니다.

python3의 경우

class ThreadWithReturnValue(Thread):
    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs={}, Verbose=None):
        Thread.__init__(self, group, target, name, args, kwargs)
        self._return = None
    def run(self):
        print(type(self._target))
        if self._target is not None:
            self._return = self._target(*self._args,
                                                **self._kwargs)
    def join(self, *args):
        Thread.join(self, *args)
        return self._return

Jake의 대답은 좋지만 스레드 풀을 사용하지 않으려면 (필요한 스레드 수를 모르지만 필요에 따라 작성하십시오) 스레드간에 정보를 전송하는 좋은 방법은 내장입니다 스레드 안전성을 제공하는 Queue.Queue 클래스

스레드 풀과 비슷한 방식으로 작동하도록 다음 데코레이터를 만들었습니다.

def threaded(f, daemon=False):
    import Queue

    def wrapped_f(q, *args, **kwargs):
        '''this function calls the decorated function and puts the 
        result in a queue'''
        ret = f(*args, **kwargs)
        q.put(ret)

    def wrap(*args, **kwargs):
        '''this is the function returned from the decorator. It fires off
        wrapped_f in a new thread and returns the thread object with
        the result queue attached'''

        q = Queue.Queue()

        t = threading.Thread(target=wrapped_f, args=(q,)+args, kwargs=kwargs)
        t.daemon = daemon
        t.start()
        t.result_queue = q        
        return t

    return wrap

그런 다음 다음과 같이 사용하십시오.

@threaded
def long_task(x):
    import time
    x = x + 5
    time.sleep(5)
    return x

# does not block, returns Thread object
y = long_task(10)
print y

# this blocks, waiting for the result
result = y.result_queue.get()
print result

데코 레이팅 된 함수는 호출 될 때마다 새 스레드를 작성하고 결과를 수신 할 큐가 포함 된 Thread 오브젝트를 리턴합니다.

최신 정보

이 답변을 게시한지 꽤 오래되었지만 여전히 뷰를 얻으므로 최신 버전의 Python 에서이 작업을 수행하는 방식을 반영하여 업데이트 할 것이라고 생각했습니다.

concurrent.futures병렬 작업을위한 고급 인터페이스를 제공하는 Python 3.2가 모듈에 추가되었습니다 . 그것은 제공 ThreadPoolExecutorProcessPoolExecutor같은 API를 사용하여 스레드 또는 프로세스 풀을 사용할 수 있습니다.

이 API의 장점 중 하나 인에 작업을 제출하는 Executor리턴한다 Future당신이 제출 한 호출의 반환 값으로 완료 개체를.

이렇게하면 queue오브젝트를 불필요 하게 부착 할 수 있어 데코레이터를 상당히 단순화 할 수 있습니다.

_DEFAULT_POOL = ThreadPoolExecutor()

def threadpool(f, executor=None):
    @wraps(f)
    def wrap(*args, **kwargs):
        return (executor or _DEFAULT_POOL).submit(f, *args, **kwargs)

    return wrap

기본 모듈 스레드 풀 실행 프로그램이 전달되지 않으면 이를 사용합니다 .

사용법은 이전과 매우 유사합니다.

@threadpool
def long_task(x):
    import time
    x = x + 5
    time.sleep(5)
    return x

# does not block, returns Future object
y = long_task(10)
print y

# this blocks, waiting for the result
result = y.result()
print result

Python 3.4 이상을 사용하는 경우이 방법 (및 일반적으로 Future 객체)을 사용하면 정말 멋진 기능 중 하나는 반환 된 미래를 감싸서 asyncio.Futurewith 로 바꿀 수 있다는 것 입니다 asyncio.wrap_future. 이것은 코 루틴과 쉽게 작동합니다.

result = await asyncio.wrap_future(long_task(10))

기본 concurrent.Future개체에 액세스 할 필요가없는 경우 데코레이터에 랩을 포함시킬 수 있습니다.

_DEFAULT_POOL = ThreadPoolExecutor()

def threadpool(f, executor=None):
    @wraps(f)
    def wrap(*args, **kwargs):
        return asyncio.wrap_future((executor or _DEFAULT_POOL).submit(f, *args, **kwargs))

    return wrap

그런 다음 CPU 집약적 또는 차단 코드를 이벤트 루프 스레드에서 푸시해야 할 때마다 꾸며진 함수에 넣을 수 있습니다.

@threadpool
def some_long_calculation():
    ...

# this will suspend while the function is executed on a threadpool
result = await some_long_calculation()

기존 코드를 변경할 필요가없는 다른 솔루션 :

import Queue
from threading import Thread

def foo(bar):
    print 'hello {0}'.format(bar)
    return 'foo'

que = Queue.Queue()

t = Thread(target=lambda q, arg1: q.put(foo(arg1)), args=(que, 'world!'))
t.start()
t.join()
result = que.get()
print result

또한 멀티 스레드 환경에 맞게 쉽게 조정할 수 있습니다.

import Queue
from threading import Thread

def foo(bar):
    print 'hello {0}'.format(bar)
    return 'foo'

que = Queue.Queue()
threads_list = list()

t = Thread(target=lambda q, arg1: q.put(foo(arg1)), args=(que, 'world!'))
t.start()
threads_list.append(t)

# Add more threads here
...
threads_list.append(t2)
...
threads_list.append(t3)
...

# Join all the threads
for t in threads_list:
    t.join()

# Check thread's return value
while not que.empty():
    result = que.get()
    print result

Parris / kindall의 답변 join / returnPython 3으로 이식 된 답변 :

from threading import Thread

def foo(bar):
    print('hello {0}'.format(bar))
    return "foo"

class ThreadWithReturnValue(Thread):
    def __init__(self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None):
        Thread.__init__(self, group, target, name, args, kwargs, daemon=daemon)

        self._return = None

    def run(self):
        if self._target is not None:
            self._return = self._target(*self._args, **self._kwargs)

    def join(self):
        Thread.join(self)
        return self._return


twrv = ThreadWithReturnValue(target=foo, args=('world!',))

twrv.start()
print(twrv.join())   # prints foo

1, 참고 Thread클래스는 파이썬 3에서 다르게 구현됩니다.


나는 kindall의 대답을 훔쳐서 조금 정리했습니다.

핵심 부분은 시간 초과를 처리하기 위해 * args 및 ** kwargs를 join ()에 추가하는 것입니다.

class threadWithReturn(Thread):
    def __init__(self, *args, **kwargs):
        super(threadWithReturn, self).__init__(*args, **kwargs)

        self._return = None

    def run(self):
        if self._Thread__target is not None:
            self._return = self._Thread__target(*self._Thread__args, **self._Thread__kwargs)

    def join(self, *args, **kwargs):
        super(threadWithReturn, self).join(*args, **kwargs)

        return self._return

아래의 업데이트 된 답변

이것은 가장 인기있는 upvoted 답변이므로 py2와 py3 모두에서 실행될 코드로 업데이트하기로 결정했습니다.

또한 Thread.join ()에 대한 이해가 부족하다는이 질문에 대한 많은 답변이 있습니다. 일부는 timeout인수 를 완전히 처리하지 못합니다 . 그러나 (1) 반환 할 수있는 대상 함수가 None있고 (2) timeoutarg를 join ()에 전달할 때 인스턴스에 대해 알아야 할 코너 케이스가 있습니다 . 이 코너 사례를 이해하려면 "테스트 4"를 참조하십시오.

py2 및 py3에서 작동하는 ThreadWithReturn 클래스 :

import sys
from threading import Thread
from builtins import super    # https://stackoverflow.com/a/30159479

if sys.version_info >= (3, 0):
    _thread_target_key = '_target'
    _thread_args_key = '_args'
    _thread_kwargs_key = '_kwargs'
else:
    _thread_target_key = '_Thread__target'
    _thread_args_key = '_Thread__args'
    _thread_kwargs_key = '_Thread__kwargs'

class ThreadWithReturn(Thread):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._return = None

    def run(self):
        target = getattr(self, _thread_target_key)
        if not target is None:
            self._return = target(*getattr(self, _thread_args_key), **getattr(self, _thread_kwargs_key))

    def join(self, *args, **kwargs):
        super().join(*args, **kwargs)
        return self._return

일부 샘플 테스트는 다음과 같습니다.

import time, random

# TEST TARGET FUNCTION
def giveMe(arg, seconds=None):
    if not seconds is None:
        time.sleep(seconds)
    return arg

# TEST 1
my_thread = ThreadWithReturn(target=giveMe, args=('stringy',))
my_thread.start()
returned = my_thread.join()
# (returned == 'stringy')

# TEST 2
my_thread = ThreadWithReturn(target=giveMe, args=(None,))
my_thread.start()
returned = my_thread.join()
# (returned is None)

# TEST 3
my_thread = ThreadWithReturn(target=giveMe, args=('stringy',), kwargs={'seconds': 5})
my_thread.start()
returned = my_thread.join(timeout=2)
# (returned is None) # because join() timed out before giveMe() finished

# TEST 4
my_thread = ThreadWithReturn(target=giveMe, args=(None,), kwargs={'seconds': 5})
my_thread.start()
returned = my_thread.join(timeout=random.randint(1, 10))

테스트 4에서 발생할 수있는 코너 케이스를 식별 할 수 있습니까?

문제는 giveMe ()가 None을 리턴 할 것으로 예상하지만 (TEST 2 참조) join ()이 시간 초과되면 None을 리턴 할 것으로 예상합니다.

returned is None 다음 중 하나를 의미합니다.

(1) giveMe ()가 반환 한 것, 또는

(2) join () 시간 초과

giveMe ()가 항상 None을 반환한다는 것을 알기 때문에이 예제는 간단합니다. 그러나 실제 상황에서 (대상이 합법적으로 None 또는 다른 것을 반환 할 수있는 경우) 우리는 무슨 일이 있었는지 명시 적으로 확인하고 싶습니다.

다음은이 코너 케이스를 해결하는 방법입니다.

# TEST 4
my_thread = ThreadWithReturn(target=giveMe, args=(None,), kwargs={'seconds': 5})
my_thread.start()
returned = my_thread.join(timeout=random.randint(1, 10))

if my_thread.isAlive():
    # returned is None because join() timed out
    # this also means that giveMe() is still running in the background
    pass
    # handle this based on your app's logic
else:
    # join() is finished, and so is giveMe()
    # BUT we could also be in a race condition, so we need to update returned, just in case
    returned = my_thread.join()

대기열 사용 :

import threading, queue

def calc_square(num, out_queue1):
  l = []
  for x in num:
    l.append(x*x)
  out_queue1.put(l)


arr = [1,2,3,4,5,6,7,8,9,10]
out_queue1=queue.Queue()
t1=threading.Thread(target=calc_square, args=(arr,out_queue1))
t1.start()
t1.join()
print (out_queue1.get())

문제에 대한 나의 해결책은 클래스에서 함수와 스레드를 래핑하는 것입니다. 풀, 큐 또는 c 유형 변수 전달을 사용할 필요가 없습니다. 또한 차단되지 않습니다. 대신 상태를 확인하십시오. 코드 끝에서 사용하는 방법의 예를 참조하십시오.

import threading

class ThreadWorker():
    '''
    The basic idea is given a function create an object.
    The object can then run the function in a thread.
    It provides a wrapper to start it,check its status,and get data out the function.
    '''
    def __init__(self,func):
        self.thread = None
        self.data = None
        self.func = self.save_data(func)

    def save_data(self,func):
        '''modify function to save its returned data'''
        def new_func(*args, **kwargs):
            self.data=func(*args, **kwargs)

        return new_func

    def start(self,params):
        self.data = None
        if self.thread is not None:
            if self.thread.isAlive():
                return 'running' #could raise exception here

        #unless thread exists and is alive start or restart it
        self.thread = threading.Thread(target=self.func,args=params)
        self.thread.start()
        return 'started'

    def status(self):
        if self.thread is None:
            return 'not_started'
        else:
            if self.thread.isAlive():
                return 'running'
            else:
                return 'finished'

    def get_results(self):
        if self.thread is None:
            return 'not_started' #could return exception
        else:
            if self.thread.isAlive():
                return 'running'
            else:
                return self.data

def add(x,y):
    return x +y

add_worker = ThreadWorker(add)
print add_worker.start((1,2,))
print add_worker.status()
print add_worker.get_results()

@JakeBiesinger 답변에 대한 @iman 의견 을 고려할 다양한 스레드 수를 갖도록 재구성했습니다.

from multiprocessing.pool import ThreadPool

def foo(bar, baz):
    print 'hello {0}'.format(bar)
    return 'foo' + baz

numOfThreads = 3 
results = []

pool = ThreadPool(numOfThreads)

for i in range(0, numOfThreads):
    results.append(pool.apply_async(foo, ('world', 'foo'))) # tuple of args for foo)

# do some other stuff in the main process
# ...
# ...

results = [r.get() for r in results]
print results

pool.close()
pool.join()

건배,

사람.


join항상 return None, Thread리턴 코드를 처리하기 위해 서브 클래스 를 작성 해야한다고 생각합니다 .


스레드 함수의 범위를 넘어서 변경 가능 변수를 정의하고 그 결과를 추가 할 수 있습니다. (또한 python3과 호환되도록 코드를 수정했습니다)

returns = {}
def foo(bar):
    print('hello {0}'.format(bar))
    returns[bar] = 'foo'

from threading import Thread
t = Thread(target=foo, args=('world!',))
t.start()
t.join()
print(returns)

이 반환 {'world!': 'foo'}

결과 입력의 핵심으로 함수 입력을 사용하는 경우 모든 고유 입력이 결과에 항목을 제공하도록 보장됩니다


이 래퍼를 사용하고 있습니다.이 래퍼 Thread는 반환 값이나 예외를 처리하면서 편안하게 실행할 수있는 모든 기능을 전환합니다 . Queue오버 헤드를 추가하지 않습니다 .

def threading_func(f):
    """Decorator for running a function in a thread and handling its return
    value or exception"""
    def start(*args, **kw):
        def run():
            try:
                th.ret = f(*args, **kw)
            except:
                th.exc = sys.exc_info()
        def get(timeout=None):
            th.join(timeout)
            if th.exc:
                raise th.exc[0], th.exc[1], th.exc[2] # py2
                ##raise th.exc[1] #py3                
            return th.ret
        th = threading.Thread(None, run)
        th.exc = None
        th.get = get
        th.start()
        return th
    return start

사용 예

def f(x):
    return 2.5 * x
th = threading_func(f)(4)
print("still running?:", th.is_alive())
print("result:", th.get(timeout=1.0))

@threading_func
def th_mul(a, b):
    return a * b
th = th_mul("text", 2.5)

try:
    print(th.get())
except TypeError:
    print("exception thrown ok.")

threading모듈 에 대한 참고 사항

스레드 함수의 편안한 반환 값 및 예외 처리는 "Pythonic"이 빈번하게 필요하며 실제로 threading표준 Thread클래스 에서 직접 모듈에 의해 제공되어야합니다 . ThreadPool간단한 작업에는 너무 많은 오버 헤드가 있습니다. 3 스레드 관리, 많은 관료주의. 불행히도 Thread레이아웃은 원래 Java에서 복사되었습니다. 예를 들어 여전히 쓸모없는 1st (!) 생성자 매개 변수에서 볼 수 group있습니다.


언급 한 바와 같이 멀티 프로세싱 풀은 기본 스레딩보다 훨씬 느립니다. 일부 답변에서 제안 된대로 대기열을 사용하는 것이 매우 효과적인 대안입니다. 많은 작은 스레드를 실행하고 사전과 결합하여 여러 답변을 복구 할 수 있도록 사전과 함께 사용했습니다.

#!/usr/bin/env python3

import threading
# use Queue for python2
import queue
import random

LETTERS = 'abcdefghijklmnopqrstuvwxyz'
LETTERS = [ x for x in LETTERS ]

NUMBERS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

def randoms(k, q):
    result = dict()
    result['letter'] = random.choice(LETTERS)
    result['number'] = random.choice(NUMBERS)
    q.put({k: result})

threads = list()
q = queue.Queue()
results = dict()

for name in ('alpha', 'oscar', 'yankee',):
    threads.append( threading.Thread(target=randoms, args=(name, q)) )
    threads[-1].start()
_ = [ t.join() for t in threads ]
while not q.empty():
    results.update(q.get())

print(results)

GuySoft의 아이디어는 훌륭하지만 객체가 Thread에서 상속받을 필요는 없으며 start ()가 인터페이스에서 제거 될 수 있다고 생각합니다.

from threading import Thread
import queue
class ThreadWithReturnValue(object):
    def __init__(self, target=None, args=(), **kwargs):
        self._que = queue.Queue()
        self._t = Thread(target=lambda q,arg1,kwargs1: q.put(target(*arg1, **kwargs1)) ,
                args=(self._que, args, kwargs), )
        self._t.start()

    def join(self):
        self._t.join()
        return self._que.get()


def foo(bar):
    print('hello {0}'.format(bar))
    return "foo"

twrv = ThreadWithReturnValue(target=foo, args=('world!',))

print(twrv.join())   # prints foo

당신의 목표를 정의
인수 소요) 1 q
) (2) 어떤 내용도 교체 return foo와를q.put(foo); return

그래서 기능

def func(a):
    ans = a * a
    return ans

될 것이다

def func(a, q):
    ans = a * a
    q.put(ans)
    return

그리고 당신은 그렇게 진행할 것입니다

from Queue import Queue
from threading import Thread

ans_q = Queue()
arg_tups = [(i, ans_q) for i in xrange(10)]

threads = [Thread(target=func, args=arg_tup) for arg_tup in arg_tups]
_ = [t.start() for t in threads]
_ = [t.join() for t in threads]
results = [q.get() for _ in xrange(len(threads))]

또한 함수 데코레이터 / 래퍼를 사용하여 기존 함수를 target수정하지 않고 사용할 수 있지만이 기본 체계를 따르십시오.


일반적인 해결책 중 하나는 다음 foo과 같은 데코레이터로 함수를 감싸는 것입니다.

result = queue.Queue()

def task_wrapper(*args):
    result.put(target(*args))

그러면 전체 코드가 다음과 같이 보일 수 있습니다

result = queue.Queue()

def task_wrapper(*args):
    result.put(target(*args))

threads = [threading.Thread(target=task_wrapper, args=args) for args in args_list]

for t in threads:
    t.start()
    while(True):
        if(len(threading.enumerate()) < max_num):
            break
for t in threads:
    t.join()
return result

노트

한 가지 중요한 문제는 반환 값이 정렬되지 않을 수 있다는 입니다. (실제로 임의의 스레드 안전 데이터 구조를 선택할 수 있으므로가에 return value반드시 저장 되는 것은 아닙니다 )queue


왜 전역 변수를 사용하지 않습니까?

import threading


class myThread(threading.Thread):
    def __init__(self, ind, lock):
        threading.Thread.__init__(self)
        self.ind = ind
        self.lock = lock

    def run(self):
        global results
        with self.lock:
            results.append(self.ind)



results = []
lock = threading.Lock()
threads = [myThread(x, lock) for x in range(1, 4)]
for t in threads:
    t.start()
for t in threads:
    t.join()
print(results)

나와 같은 인형에 대해이 작업을 수행하는 매우 간단한 방법 :

import queue
import threading

# creating queue instance
q = queue.Queue()

# creating threading class
class AnyThread():
    def __init__ (self):
        threading.Thread.__init__(self)

    def run(self):
        # in this class and function we will put our test target function
        test()

t = AnyThread()

# having our test target function
def test():
    # do something in this function:
    result = 3 + 2
    # and put result to a queue instance
    q.put(result)

for i in range(3): #calling our threading fucntion 3 times (just for example)
    t.run()
    output = q.get() # here we get output from queue instance
    print(output)

>>> 5
>>> 5
>>> 5

여기서 중요한 것은 queue모듈입니다. queue.Queue()인스턴스를 만들어 함수에 포함시킵니다. 우리는 나중에 스레드를 넘어서는 결과를 제공합니다.

테스트 함수에 인수가 전달 된 예를 하나 더 참조하십시오.

import queue
import threading

# creating queue instance
q = queue.Queue()

# creating threading class
class AnyThread():
    def __init__ (self):
        threading.Thread.__init__(self)

    def run(self, a, b):
        # in this class and function we will put our execution test function
        test(a, b)

t = AnyThread()

# having our test target function
def test(a, b):
    # do something in this function:
    result = a + b
    # and put result to a queue instance
    q.put(result)

for i in range(3): #calling our threading fucntion 3 times (just for example)
    t.run(3+i, 2+i)
    output = q.get() # here we get output from queue instance
    print(output)

>>> 5
>>> 7
>>> 9

Kindall의 대답 Python3에서

class ThreadWithReturnValue(Thread):
    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs={}, *, daemon=None):
        Thread.__init__(self, group, target, name, args, kwargs, daemon)
        self._return = None 

    def run(self):
        try:
            if self._target:
                self._return = self._target(*self._args, **self._kwargs)
        finally:
            del self._target, self._args, self._kwargs 

    def join(self,timeout=None):
        Thread.join(self,timeout)
        return self._return

함수 호출에서 True 또는 False 만 유효성을 검사 해야하는 경우 더 간단한 해결책은 전역 목록을 업데이트하는 것입니다.

import threading

lists = {"A":"True", "B":"True"}

def myfunc(name: str, mylist):
    for i in mylist:
        if i == 31:
            lists[name] = "False"
            return False
        else:
            print("name {} : {}".format(name, i))

t1 = threading.Thread(target=myfunc, args=("A", [1, 2, 3, 4, 5, 6], ))
t2 = threading.Thread(target=myfunc, args=("B", [11, 21, 31, 41, 51, 61], ))
t1.start()
t2.start()
t1.join()
t2.join()

for value in lists.values():
    if value == False:
        # Something is suspicious 
        # Take necessary action 

필요한 조치를 취하기 위해 스레드 중 하나가 잘못된 상태를 리턴했는지 여부를 찾으려면 더 유용합니다.

참고 URL : https://stackoverflow.com/questions/6893968/how-to-get-the-return-value-from-a-thread-in-python

반응형