threading
정리logging
활용기본적으로 스레드는 디버깅이 어렵기 때문에 logging
을 통해 실행 과정을 잘 표현하는 것이 중요하다.
import logging
# 기본 설정
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='/path/to/logfile.log'
datefmt='%Y-%m-%d %H:%M:%S'
)
로그 레벨
DEBUG
: 가장 낮은 레벨. 상세한 정보를 기록할 때 사용
INFO
: 일반적인 정보를 기록할 때 사용
WARNING
: 예상치 못한 일이 발생, 문제가 될만한 상황을 기록할 때 사용
ERROR
: 프로그램의 일부 기능이 제대로 동작하지 않을 때 사용
CRITICAL
: 프로그램 자체가 정상적으로 동작할 수 없을 때 사용
import logging
import threading
# 스레드 실행 함수
def thread_func(name):
logging.info("Sub-Thread %s: starting", name)
"""
Thread task code
"""
logging.info("Sub-Thread %s: finishing", name)
# 메인스레드 영역
if __name__ == "__main__":
# Logging format 설정
format = "%(asctime)s: %(message)s"
logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S")
logging.info("Main-Thread : before creating thread")
# 함수 인자 확인
x = threading.Thread(target=thread_func, args=("First",))
logging.info("Main-Thread : before running thread")
# 서브 스레드 시작
x.start()
logging.info("Main-Thread : wait for the thread to finish")
# x.join() # x 스레드 종료까지 메인스레드 대기
logging.info("Main-Thread : all done")
메인 스레드 종료 시 서브스레드 함께 종료
import logging
import threading
# 스레드 실행 함수
def thread_func(name):
logging.info("Sub-Thread %s: starting", name)
"""
Thread task code
"""
logging.info("Sub-Thread %s: finishing", name)
# 메인스레드 영역
if __name__ == "__main__":
# Logging format 설정
format = "%(asctime)s: %(message)s"
logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S")
logging.info("Main-Thread : before creating thread")
# 방법 1. 직접 daemon 옵션 추가
x = threading.Thread(target=thread_func, args=("First",), daemon=True)
# 방법 2. 속성 설정
# x = .Thread(target=thread_func, args=("First",))
# x.daemon = True
logging.info("Main-Thread : before running thread")
# 서브 스레드 시작
x.start()
logging.info("Main-Thread : wait for the thread to finish")
logging.info("Main-Thread : all done")
# 이 시점(메인스레드 종료)에서 서브스레드 강제 종료
import logging
from concurrent.futures import ThreadPoolExecutor
# 스레드 실행 함수
def task(name):
logging.info("Sub-Thread %s: starting", name)
"""
Thread task
"""
logging.info("Sub-Thread %s: finishing result: %d", name, result)
return task_result
# 메인 영역
def main():
# Logging format 설정
format = "%(asctime)s: %(message)s"
logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S")
logging.info("Main-Thread : before creating and running thread")
""" 방법1. 직접 스레드 추가 """
# max_workers : 작업의 개수가 넘어가면 직접 설정이 유리
executor = ThreadPoolExecutor(max_workers=3)
task1 = executor.submit(task, ('First',))
task2 = executor.submit(task, ('Second',))
# 결과 값 있을 경우
# print(task1.result())
# print(task2.result())
""" 방법2. with 구문 사용 """
with ThreadPoolExecutor(max_workers=3) as executor:
# 곧바로 결과값 받아오기
tasks = executor.map(task, ['First', 'Second'])
# 결과값 리스트 확인
# print(list(tasks))
# 스레드 객체 리스트 받기
threads = [excuter.submit(task, idx) for idx in range(5)]
# 스레드 객체를 통한 결과값 확인
# print([t.result() for t in threads])
logging.info("Main-Thread : all done")
if __name__ == '__main__':
main()
ThreadPoolExecutor는 내부적으로 작업 대기열로서 큐를 사용