스레드에서 값 반환
파이썬의 부모에게 튜플이나 선택한 값을 반환하는 스레드를 얻으려면 어떻게해야합니까?
스레드를 시작하기 전에 Queue.Queue 를 인스턴스화 하고 스레드의 인수 중 하나로 전달 하는 것이 좋습니다 . 스레드가 완료되기 전에 .put
인수로받은 큐의 결과입니다. 부모 캔 .get
또는 .get_nowait
의지 그것.
대기열은 일반적으로 Python에서 스레드 동기화 및 통신을 정렬하는 가장 좋은 방법입니다. 대기열은 본질적으로 스레드로부터 안전한 메시지 전달 수단입니다. 일반적으로 멀티 태스킹을 구성하는 가장 좋은 방법입니다!-)
스레드가 완료 될 때까지 기다리기 위해 join ()을 호출하는 경우 단순히 결과를 Thread 인스턴스 자체에 첨부 한 다음 join ()이 반환 된 후 기본 스레드에서 검색 할 수 있습니다.
반면에 스레드가 완료되었고 결과를 사용할 수 있다는 것을 어떻게 발견 할 것인지 알려주지 않습니다. 이미 그렇게 할 수있는 방법이 있다면 아마도 결과를 얻는 가장 좋은 방법을 당신 (그리고 우리에게 말하면 우리)에게 알려줄 것입니다.
Queue 인스턴스를 매개 변수로 전달한 다음 반환 객체를 대기열에 .put ()해야합니다. 어떤 객체를 넣든 queue.get ()을 통해 반환 값을 수집 할 수 있습니다.
견본:
queue = Queue.Queue()
thread_ = threading.Thread(
target=target_method,
name="Thread1",
args=[params, queue],
)
thread_.start()
thread_.join()
queue.get()
def target_method(self, params, queue):
"""
Some operations right here
"""
your_return = "Whatever your object is"
queue.put(your_return)
여러 스레드에 사용 :
#Start all threads in thread pool
for thread in pool:
thread.start()
response = queue.get()
thread_results.append(response)
#Kill all threads
for thread in pool:
thread.join()
나는이 구현을 사용하고 그것은 나를 위해 잘 작동합니다. 그렇게하시기 바랍니다.
람다 를 사용 하여 대상 스레드 함수를 래핑하고 큐를 사용하여 반환 값을 부모 스레드로 다시 전달합니다 . (원래 대상 함수는 추가 큐 매개 변수없이 변경되지 않습니다.)
샘플 코드 :
import threading
import queue
def dosomething(param):
return param * 2
que = queue.Queue()
thr = threading.Thread(target = lambda q, arg : q.put(dosomething(arg)), args = (que, 2))
thr.start()
thr.join()
while not que.empty():
print(que.get())
산출:
4
아무도 당신이 그것을 mutable로 전달할 수 있다고 언급하지 않은 것에 놀랐습니다.
>>> thread_return={'success': False}
>>> from threading import Thread
>>> def task(thread_return):
... thread_return['success'] = True
...
>>> Thread(target=task, args=(thread_return,)).start()
>>> thread_return
{'success': True}
아마도 이것은 내가 알지 못하는 주요 문제가 있습니다.
또 다른 접근 방식은 콜백 함수를 스레드에 전달하는 것입니다. 이렇게하면 새 스레드에서 언제든지 부모에게 값을 반환하는 간단하고 안전하며 유연한 방법이 제공됩니다.
# A sample implementation
import threading
import time
class MyThread(threading.Thread):
def __init__(self, cb):
threading.Thread.__init__(self)
self.callback = cb
def run(self):
for i in range(10):
self.callback(i)
time.sleep(1)
# test
import sys
def count(x):
print x
sys.stdout.flush()
t = MyThread(count)
t.start()
동기화 된 큐 모듈을 사용할 수 있습니다 .
알려진 ID로 데이터베이스에서 사용자 정보를 확인해야한다고 생각하십시오.
def check_infos(user_id, queue):
result = send_data(user_id)
queue.put(result)
이제 다음과 같은 데이터를 얻을 수 있습니다.
import queue, threading
queued_request = queue.Queue()
check_infos_thread = threading.Thread(target=check_infos, args=(user_id, queued_request))
check_infos_thread.start()
final_result = queued_request.get()
POC :
import random
import threading
class myThread( threading.Thread ):
def __init__( self, arr ):
threading.Thread.__init__( self )
self.arr = arr
self.ret = None
def run( self ):
self.myJob( self.arr )
def join( self ):
threading.Thread.join( self )
return self.ret
def myJob( self, arr ):
self.ret = sorted( self.arr )
return
#Call the main method if run from the command line.
if __name__ == '__main__':
N = 100
arr = [ random.randint( 0, 100 ) for x in range( N ) ]
th = myThread( arr )
th.start( )
sortedArr = th.join( )
print "arr2: ", sortedArr
글쎄요, 파이썬 스레딩 모듈에는 잠금과 관련된 조건 객체가 있습니다. 하나의 메서드 acquire()
는 기본 메서드에서 반환 된 값을 반환합니다. 자세한 정보 : Python 조건 객체
Based on jcomeau_ictx's suggestion. The simplest one I came across. Requirement here was to get exit status staus from three different processes running on the server and trigger another script if all three are successful. This seems to be working fine
class myThread(threading.Thread):
def __init__(self,threadID,pipePath,resDict):
threading.Thread.__init__(self)
self.threadID=threadID
self.pipePath=pipePath
self.resDict=resDict
def run(self):
print "Starting thread %s " % (self.threadID)
if not os.path.exists(self.pipePath):
os.mkfifo(self.pipePath)
pipe_fd = os.open(self.pipePath, os.O_RDWR | os.O_NONBLOCK )
with os.fdopen(pipe_fd) as pipe:
while True:
try:
message = pipe.read()
if message:
print "Received: '%s'" % message
self.resDict['success']=message
break
except:
pass
tResSer={'success':'0'}
tResWeb={'success':'0'}
tResUisvc={'success':'0'}
threads = []
pipePathSer='/tmp/path1'
pipePathWeb='/tmp/path2'
pipePathUisvc='/tmp/path3'
th1=myThread(1,pipePathSer,tResSer)
th2=myThread(2,pipePathWeb,tResWeb)
th3=myThread(3,pipePathUisvc,tResUisvc)
th1.start()
th2.start()
th3.start()
threads.append(th1)
threads.append(th2)
threads.append(th3)
for t in threads:
print t.join()
print "Res: tResSer %s tResWeb %s tResUisvc %s" % (tResSer,tResWeb,tResUisvc)
# The above statement prints updated values which can then be further processed
The following wrapper function will wrap an existing function and return an object which points both to the thread (so that you can call start()
,join()
, etc. on it) as well as access/view its eventual return value.
def threadwrap(func,args,kwargs):
class res(object): result=None
def inner(*args,**kwargs):
res.result=func(*args,**kwargs)
import threading
t = threading.Thread(target=inner,args=args,kwargs=kwargs)
res.thread=t
return res
def myFun(v,debug=False):
import time
if debug: print "Debug mode ON"
time.sleep(5)
return v*2
x=threadwrap(myFun,[11],{"debug":True})
x.thread.start()
x.thread.join()
print x.result
It looks OK, and the threading.Thread
class seems to be easily extended(*) with this kind of functionality, so I'm wondering why it isn't already there. Is there a flaw with the above method?
(*) Note that husanu's answer for this question does exactly this, subclassing threading.Thread
resulting in a version where join()
gives the return value.
For easy programs the above answeres look a little bit like overkill to me. I would en-nicen the mutable approach:
class RetVal:
def __init__(self):
self.result = None
def threadfunc(retVal):
retVal.result = "your return value"
retVal = RetVal()
thread = Thread(target = threadfunc, args = (retVal))
thread.start()
thread.join()
print(retVal.result)
ReferenceURL : https://stackoverflow.com/questions/1886090/return-value-from-thread
'Nice programing' 카테고리의 다른 글
MSTest의 글로벌 테스트 초기화 방법 (0) | 2020.12.29 |
---|---|
JUnit 테스트가 예외를 발생시키는 잘못된 양식? (0) | 2020.12.29 |
Eclipse에서 기본 디버그를 만들고 구성을 실행하는 방법은 무엇입니까? (0) | 2020.12.29 |
리프팅 운영자는 무엇입니까? (0) | 2020.12.29 |
Windows 경로에 실행 파일이 있는지 확인 (0) | 2020.12.29 |