_thread — 저수준 스레딩 API
_thread — 저수준 스레딩 API (Low-level threading API)
이 모듈은 여러 스레드(가볍게는 '경량 프로세스' 또는 '태스크'라고도 불러요)로 작업할 때 쓰는 저수준 원시 도구들을 제공해요. 여러 스레드가 전역 데이터 공간을 공유하면서 동시에 실행되죠. 동기화를 위해 간단한 락(mutex 또는 이진 세마포어라고도 불러요)도 제공해요. threading 모듈은 이 모듈 위에 만들어진, 쓰기 쉽고 더 고수준인 스레딩 API예요.
출처: Python 표준 라이브러리
본문
이 모듈은 여러 스레드(경량 프로세스 또는 태스크라고도 불려요) — 즉 전역 데이터 공간을 공유하는 여러 제어 흐름 — 로 작업하기 위한 저수준 원시 요소를 제공해요. 동기화를 위해서는 간단한 락(mutex 또는 binary semaphore라고도 불려요)을 제공하죠. threading 모듈은 이 모듈 위에 지어진, 쓰기 쉽고 더 고수준인 스레딩 API예요.
3.7 버전 변경: 이 모듈은 예전엔 선택적이었는데, 이제는 항상 사용할 수 있어요.
이 모듈은 다음의 상수와 함수들을 정의해요.
exception _thread.error
스레드 특유의 오류가 있을 때 발생해요.
3.3 버전 변경: 이제 내장
RuntimeError의 동의어예요.
_thread.start_new_thread(function, args[, kwargs])
새 스레드를 시작하고 그 식별자를 반환해요. 스레드는 인자 목록 args(튜플이어야 해요)로 function을 실행해요. 선택적 kwargs 인자는 키워드 인자의 사전을 지정해요.
- 함수가 반환되면 스레드는 조용히 종료돼요.
- 함수가 처리되지 않은 예외로 끝나면
sys.unraisablehook()이 호출돼서 예외를 처리해요. 후크 인자의object속성이function이에요. 기본적으로 스택 트레이스를 출력하고 스레드가 종료돼요(다른 스레드들은 계속 실행됨). - 함수가
SystemExit예외를 발생시키면 조용히 무시돼요.
_thread.start_new_thread 감사 이벤트를 인자 function, args, kwargs로 발생시켜요.
3.8 버전 변경: 이제
sys.unraisablehook()이 처리되지 않은 예외를 처리하는 데 쓰여요.
_thread.interrupt_main(signum=signal.SIGINT, /)
메인 스레드에 신호가 도착하는 효과를 시뮬레이션해요. 다른 스레드가 이 함수로 메인 스레드를 인터럽트할 수 있어요. 다만 인터럽션이 즉시 일어난다는 보장은 없어요.
signum이 주어지면 시뮬레이션할 신호의 번호예요. 주어지지 않으면 signal.SIGINT를 시뮬레이션해요. 주어진 신호가 Python이 처리하지 않는 것(signal.SIG_DFL 또는 signal.SIG_IGN으로 설정된)이라면 이 함수는 아무것도 하지 않아요.
3.10 버전 변경: 신호 번호를 지정할 수 있는
signum인자가 추가됐어요.주의: 이 함수는 실제 신호를 발생시키는 게 아니라, 관련 핸들러(존재한다면)를 호출하도록 예약해요. 진짜로 신호를 발생시키고 싶다면
signal.raise_signal()을 사용하세요.
_thread.exit()
SystemExit 예외를 발생시켜요. 잡히지 않으면 스레드가 조용히 종료돼요.
_thread.allocate_lock()
새 락 객체를 반환해요. 락의 메서드는 아래에서 설명할게요. 락은 처음에 잠기지 않은(unlocked) 상태예요.
_thread.get_ident()
현재 스레드의 '스레드 식별자(thread identifier)'를 반환해요. 0이 아닌 정수예요. 그 값 자체에는 직접적인 의미가 없고, 예를 들어 스레드별 데이터의 사전을 인덱싱할 때 쓰는 '매직 쿠키'로 사용하기 위한 거예요. 스레드 식별자는 스레드가 종료되고 다른 스레드가 만들어지면 재활용될 수 있어요.
_thread.get_native_id()
커널이 할당한 현재 스레드의 네이티브 정수 스레드 ID를 반환해요. 0 이상의 정수예요. 이 값은 시스템 전체에서 특정 스레드를 고유하게 식별하는 데 쓰일 수 있어요(스레드가 종료될 때까지, 종료 후엔 OS가 그 값을 재활용할 수 있어요).
- 가용성: Windows, FreeBSD, Linux, macOS, OpenBSD, NetBSD, AIX, DragonFlyBSD, GNU/kFreeBSD.
- 3.8 버전에서 추가.
- 3.13 버전 변경: GNU/kFreeBSD 지원 추가.
_thread.stack_size([size])
새 스레드를 만들 때 사용하는 스레드 스택 크기를 반환해요. 선택적 size 인자는 이후에 만들어질 스레드에 사용할 스택 크기를 지정하고, 0(플랫폼 또는 설정된 기본값 사용)이거나 최소 32,768(32 KiB) 이상의 양의 정수여야 해요. size를 지정하지 않으면 0이 사용돼요. 스레드 스택 크기 변경이 지원되지 않으면 RuntimeError가 발생해요. 지정된 스택 크기가 유효하지 않으면 ValueError가 발생하고 스택 크기는 변경되지 않아요. 32 KiB는 인터프리터 자체에 충분한 스택 공간을 보장하기 위한 현재 최소 지원 스택 크기예요. 일부 플랫폼에서는 스택 크기에 특정 제약이 있을 수 있는데, 예를 들어 최소 32 KiB보다 큰 스택 크기를 요구하거나 시스템 메모리 페이지 크기의 배수로 할당해야 할 수 있어요. 자세한 내용은 플랫폼 문서를 참고하세요(4 KiB 페이지가 흔하고, 더 구체적인 정보가 없다면 스택 크기의 배수로 4096을 쓰는 게 권장돼요).
- 가용성: Windows, pthreads.
- POSIX 스레드를 지원하는 Unix 플랫폼.
_thread.TIMEOUT_MAX
Lock.acquire의 timeout 매개변수에 허용되는 최대값이에요. 이 값보다 큰 timeout을 지정하면 OverflowError가 발생해요.
3.2 버전에서 추가.
class _thread.LockType
락 객체의 타입이에요. 락 객체는 다음 메서드들을 가져요.
acquire(blocking=True, timeout=-1)
선택 인자 없이 호출하면 이 메서드는 무조건 락을 획득해요. 필요하다면 다른 스레드가 풀어 줄 때까지 기다리죠(한 번에 한 스레드만 락을 획득할 수 있어요 — 이게 락이 존재하는 이유예요).
blocking 인자가 있으면 동작이 그 값에 달려요. False면 대기 없이 즉시 획득할 수 있을 때만 락을 획득하고, True면 위처럼 무조건 획득해요.
부동소수 timeout 인자가 있고 양수면, 반환 전 최대 대기 시간(초)을 지정해요. 음수 timeout은 무제한 대기를 지정해요. blocking이 False일 때는 timeout을 지정할 수 없어요.
반환값은 락을 성공적으로 획득하면 True, 아니면 False예요.
3.2 버전 변경:
timeout매개변수가 새로 추가됐어요. 3.2 버전 변경: POSIX에서 락 획득이 신호로 인터럽트될 수 있게 됐어요. 3.14 버전 변경: Windows에서도 락 획득이 신호로 인터럽트될 수 있게 됐어요.
release()
락을 풀어요. 락은 이전에 획득된 상태여야 하지만, 반드시 같은 스레드가 획득했을 필요는 없어요.
locked()
락의 상태를 반환해요. 어떤 스레드가 획득했으면 True, 아니면 False예요.
이 메서드들 외에도 락 객체는 with 문으로 쓸 수 있어요.
import _thread
a_lock = _thread.allocate_lock()
with a_lock:
print("a_lock is locked while this executes")
주의 사항 (Caveats)
- 인터럽트는 항상 메인 스레드로 가요(
KeyboardInterrupt예외를 그 스레드가 받아요). sys.exit()를 호출하거나SystemExit예외를 발생시키는 것은_thread.exit()를 호출하는 것과 같아요.- 메인 스레드가 종료될 때 다른 스레드가 살아남을지는 시스템이 정의해요. 대부분의 시스템에서는
try … finally절이나 객체 소멸자를 실행하지 않고 그들을 죽여요.