본문 바로가기
Code/Python

파이썬의 스케쥴러, sched

by hyelog 2024. 2. 4.

파이썬의 표준 라이브러리의 일부인 sched 모듈에 대해 알아보자.

sched 모듈이란

파이썬에서 제공하는  이벤트 기반의 스케줄링을 위한 간결하고 효과적인 도구이다.

모듈은 특정 시간에 실행되어야 하는 함수나 작업을 예약하는 기능을 제공하며, 주로 단일 스레드 환경에서 사용되는 특징을 가지고 있다. 

사용자는 sched.scheduler 클래스를 활용하여 스케쥴러 객체를 생성하고, 만들어진 객체를 활용하여 이벤트를 관리하고, 스케쥴링한다.

스케쥴러 객체

스케쥴러 객체는 스케줄을 위해 시간에 관한 함수를 필요로 한다.

class sched.scheduler(timefunc=time.monotonic, delayfunc=time.sleep)

언제 이벤트를 실행할지, 얼마나 대기할지를 알려주기 위함이다.

대개 시간함수는 time.time을 자주 활용하고, 지연함수는 time.sleep을 활용한다.

 

# 객체 생성하기

import sched, time
s = sched.scheduler(time.time, time.sleep)

 

# 이벤트 스케쥴링 하기

이 스케쥴링 객체는 2가지 방법으로 이벤트를 스케쥴링 할 수 있는데

1. enter 메서드 : 지정된 시간만큼 지연된 후에 이벤트를 실행한다. 이벤트는 (지연시간, 우선순위, 실행함수, 인자)의 형태로 제공된다.

def job(name):
    print(f"이벤트 {name} 실행: {time.time()}")

s.enter(delay=10, priority=1, action=job, argument=('첫 번째',))

 

2. enterabs 메서드 : 절대적인 시간에 이벤트를 실행한다. 즉, 이벤트를 실행시킬 정확한 시간을 지정할 수 있음을 의미한다.

future_time = time.time() + 15
s.enterabs(future_time, 1, job, argument=('두 번째',))

 

# 이벤트 실행하기

run 메서드를 호출하면 스케줄러는 예약된 모든 이벤트를 순서대로 실행한다.

이 메서드는 blocking 매개변수가 true(default)로 설정되면, 모든 이벤트가 실행될 때까지 실행을 멈추지 않는다.

즉, 메서드 내부에서 모든 이벤트가 완료될 때까지 제어가 반환되지 않는다.

 

blocking 매개변수가 false로 설정되면 , run 메서드는 현재 대기 중인 이벤트가 없을 때 예약된 다음 이벤트가 실행될 때까지 기다리지 않고  즉시 반환한다.

 이는 스케줄러를 비동기적으로 실행하고자 할 때 유용하다. (스케쥴러를 더 유연하게 제어할 수 있음!)

 

action이나 delayfunc는 예외를 발생시킬 수 있다.

두 경우 모두, 스케줄러는 일관된 상태를 유지(중단되지 않음)하고 예외를 전파한다. 

 

action에 의해 예외가 발생하면, 이후에 run()을 호출할 때 이벤트를 실행하려고 하지 않는다.

일련의 이벤트가 다음 이벤트 이전에 사용 가능한 시간보다 실행하는 데 더 오래 걸리면, 스케줄러는 단순히 지연된다.

어떤 이벤트도 삭제되지 않는다!!! (더는 적절하지 않은 이벤트를 취소할 책임은 호출 코드에 있다)

s.run()

 

# 이벤트 취소하기

cancel 메서드를 사용하면 이미 스케줄 된 이벤트를 취소할 수 있다.

이 메서드는 취소하고자 하는 이벤트의 참조를 인자로 받는다.

event = s.enter(30, 1, job, ('취소될 이벤트',))
s.cancel(event)

 

# 간단한 예제 코드

import sched, time

# 이벤트 출력 함수
def job(name):
    print(f"이벤트 {name} 실행: {time.time()}")

# 스케줄러 생성
s = sched.scheduler(time.time, time.sleep)

# 이벤트 스케줄링
s.enter(10, 1, job, argument=('첫 번째',))
future_time = time.time() + 15
s.enterabs(future_time, 1, job, argument=('두 번째',))

# 스케줄러 실행
s.run()

 

sched 모듈의 장점

1. 간단한 API:

sched 모듈은 enter, enterabs, run, cancel과 같은 간단한 메서드로 스케쥴링이 가능하다.

이로 인해 코드 유지가 비교적 용이하다.

 

2. 스레드 안전성:

sched 모듈은 단일 스레드 환경에서 작동하기 때문에,

멀티스레딩에서 발생할 수 있는 여러 스레드가 동시에 자원에 접근하는 경쟁 상태(race conditions)를 피할 수 있고,

공유 자원에 대한 접근제어를 위한 데이터 동기화 메커니즘이 필요하지 않다.

이는 특히 복잡한 동시성 관리가 필요 없는 애플리케이션에 적합하다.

 

3. 리소스 사용 최적화:

sched 모듈은 추가적인 스레드를 생성하거나 관리하지 않기 때문에, 메모리와 CPU 자원을 효율적으로 사용한다.

이는 특히 리소스가 제한된 환경에서 유용할 수 있다.

 

그래서, 우린 sched를 썼구나.

사실 이 모듈을 알게 된 계기는 얼마 전이다.

회사에서 센서 데이터를 다루는 공간(자세한 이야기는 혹시 몰라 하지 않습니다ㅎㅎ)에 모델을 심어야 했다.

거기서 생긴 제약조건이 아주 작은 리소스 공간을 사용해야 한다는 점이었다.

주기적으로 모델이 돌아가야 하지만,  리소스를 넘지 않게 여러 공정에 관한 모델을 심어야 하다 보니,

스케쥴링에 큰 메모리를 할당할 수 없었을 것이다. 

최대한 가볍게 운영코드를 짜야했는데 거기에 딱 들어맞았던 모듈이 sched가 아니었을까 조심스레 추측해 본다.

sched의 장점을 충분히 발휘할 수 있는 서비스라면 사용해봐도 좋을 것 같다

 

 

댓글