본문 바로가기
프로그래밍/개발 팁 공유

[python3 & 2] 쓰레드 thread 에서 반환값 return value 얻는 방법은?

by 김모범 2023. 4. 17.
반응형

thread는 프로그램에 여러 로직 간에 동시성을 갖게 해주는 아주 중요한 요소입니다.

 

보통의 프로그램은 하나의 로직으로만 수행되지 않고 여러 로직이 동시적으로 수행되어 지게 됩니다.

 

오늘 포스팅에서는 쓰레드 thread 에서 반환값 return value 를 얻는 방법에 대하여 포스팅 하려고 합니다.


방법1.  전역번수 사용

일반적으로 쓰레드를 시작하게 되면 반환값은 없이 해당 쓰레드는 로직을 마치면 자동으로 종료되게 됩니다.

그 전에 원하는 값을 공통으로 접근 할 수 있는 변수에 저장할 수 있다면 반환값이 있는 함수처럼 사용할 수 있게 됩니다.

 

from threading import Lock
from threading import Thread

#전역변수
data_list = []
lock_for_data_list = Lock()

def some_fuction():
	#전역변수를 함수 내에서 사용하기 위하여 내부 선언
	global data_list
	data = None
    
	#some logic...
    
	#다른 쓰레드에서 접근을 막기 위한 lock
	lock_for_data_list.acquire()
	data_list.append(data)
	lock_for_data_list.release()
    
def main():
	global data_list
    
	t = Thread(target=some_function)
	t.start()
    
	t.join()
	print(data_list)
    
	return
    
if __name__ == '__main__':
	main()

위 코드에는 세가지 중요한 지점이 있습니다.

첫번째는 정보를 공유할 전역 변수 입니다. 함수 바깥쪽에 사용할 변수를 선언한 뒤, 사용할 함수 안에서 global 키워드와 함께 내부 선언을 해주시면 사용할 준비가 되게 됩니다.

 

두번째는 전역변수 공유 시, dead lock 등 오류를 발생을 방지하기 위한 Lock 입니다. 동시에 같은 데이터에 접근하게 될 경우, 프로그램에 치명적인 오류가 발생하거나 데이터가 부정확해지는 일이 발생할 수 있으므로, 한번에 한 쓰레드에서만 접근할 수 있도록 Lock() 을 사용하여 구역을 묶어 두는것이 일반적입니다.

 

세번째는 쓰레드 Thread 종료 시까지 기다릴 수 있도록 하는 join() 입니다. join() 사용 시, 해당 쓰레드의 함수가 종료될 때까지 기다리게됩니다. 

 

위 세가지 내용이 모두 위의 코드에 쓰였으니 참고 하시면 좋겠습니다.

 

방법2. Thread 클래스를 상속받아 값을 반환하는 클래스

간단하게 코드부터 소개하고 사용법을 공유하겠습니다.(python3)

from threading import Thread

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

위에 작성된 ThreadWithReturnValue 클래스는 Thread 클래스를 상속받아 init 과 run, join 함수를 재정의 하였습니다. (출처 :

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

 

사용방법은 일반적인 thread 의 사용법과 모두 동일하지만 join 에 반환값이 발생하게 된다.

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

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

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

위 소개한 두가지 방법을 개념만 잘 잡고 있다면 thread 를 사용하는 것이 어렵지 않게 될 것입니다.

 

더 좋은 방법이 있다면 소개해 주시면 감사드리겠습니다^^

 

이상 포스팅 마치겠습니다.

 

찾아와 주신 모든 분들께 감사드립니다(_ _)

반응형

댓글