[python] 쓰레드(Thread)

이번 글에서는 파이썬에서 쓰레드를 사용하는 방법에 대해 간단히 알아보겠습니다.

쓰레드

개발을 하다보면 여러 개의 작업을 동시에 실행해야하는 경우가 자주 있습니다.
이런 경우 파이썬에서는 threading 모듈을 제공해 줍니다.

import threading
threading 모듈

파이썬에서 스레드를 생성하기 위해 threading 모듈을 사용합니다. 아래는 쓰레드로 1~9까지 출력하는 코드입니다.

import threading

# 스레드 기본
def print_no():
    print("Thread Start")
    for i in range(1, 10):
        print(i)
        time.sleep(1)
    print("="*5, "Thread end")

if __name__ == "__main__":
    t = threading.Thread(target=print_no)
    t.start()

파라미터 전달

쓰레드에 파라미터를 전달할 때는 Thread 객체를 생성할 때 args에 튜플로 파라미터를 전달하면 됩니다.
아래는 예제 코드입니다.

import threading, time

# 파라미터 전달
def print_no(range_from, range_to):
    print("Thread Start")
    for i in range(range_from, range_to):
        print(i)
        time.sleep(1)
    print("="*5, "Thread end")

if __name__ == "__main__":
    t = threading.Thread(target=print_no, args=(10, 20)) # rage_from과 rage_to에 10, 20 전달
    t.start()

10과 20이 전달되어 출력하는 것을 볼 수 있습니다.

join

아래 코드의 실행 결과를 먼저 보겠습니다.

import threading

def print_no():
    print("Thread Start")
    for i in range(1, 10):
        print(i)
        time.sleep(1)
    print("="*5, "Thread end")

if __name__ == "__main__":
    print("="*5, "main start")
    t = threading.Thread(target=print_no)
    t.start()
    print("="*5, "main end")

실행 결과를 보면 메인 쓰레드(=__main__)에서 서브 쓰레드(t)를 생성하였고, 서브 쓰레드는 서브 쓰레드대로 실행되다 종료되고 메인 쓰레드는 메인 쓰레드 대로 실행이 되다가 종료 됩니다.
파이썬에서 쓰레드는 생성이 되어 시작하면 기본적으로, 메인 쓰레드가 종료되어도 서브 쓰레드는 끝까지 작업을 수행합니다.
서브 쓰레드가 종료될 때까지 메인 쓰레드를 종료하지 않으려면 join함수를 사용하면 됩니다.

import threading

# join
def print_no():
    print("Thread Start")
    for i in range(1, 10):
        print(i)
        time.sleep(1)
    print("="*5, "Thread end")

if __name__ == "__main__":
    print("="*5, "main start")
    t = threading.Thread(target=print_no)
    t.start()
    
    t.join() # 대기
    
    print("="*5, "main end")

위 코드와 다르게 서브 쓰레드가 종료되고 메인 쓰레드가 종료되는 것을 볼 수 있습니다.

daemon

위와 반대로 메인 쓰레드가 종료되면 서브 쓰레드를 종료시켜야 할 경우도 있습니다.
이 경우에는 setDeamon 함수를 사용하여 True로 설정하면 메인 쓰레드 종료 시 서브 쓰레드도 종료됩니다.

import threading

# deamon
def print_no():
    print("Thread Start")
    for i in range(1, 10):
        print(i)
        time.sleep(1)
    print("="*5, "Thread end")

if __name__ == "__main__":
    print("="*5, "main start")
    t = threading.Thread(target=print_no)    
    t.setDaemon(True) # deamon    
    t.start()
    
    time.sleep(0.5)
    print("="*5, "main end")

Thread 클래스 상속

Thread 클래스를 상속받아 쓰레드를 생성했을 땐 run 메소드를 재정의해서 실행할 코드를 입력해야 합니다.
아래 코드는 Thread 클래스를 상속받은 예제 코드입니다.

import threading, time

# Thread 클래스 상속
class PrintThread(threading.Thread):
    def __init__(self, range_from, range_to):
        super().__init__()
        self.range_from = range_from
        self.range_to = range_to
    
    # run 재정의
    def run(self):
        print("Thread Start")
        for i in range(self.range_from, self.range_to):
            print(i)
            time.sleep(1)
        print("Thread end")

if __name__ == "__main__":
    t = PrintThread(20, 30)
    t.start()

이상으로 쓰레드에 대해 간단히 알아보았습니다.