Nice programing

스레드에서 값 반환

nicepro 2020. 12. 29. 08:26
반응형

스레드에서 값 반환


파이썬의 부모에게 튜플이나 선택한 값을 반환하는 스레드를 얻으려면 어떻게해야합니까?


스레드를 시작하기 전에 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

반응형