[Django] 서버 실행중에 함수 주기적으로 호출하기

8379 단어 drfdjangodjango

django apscheduler

서버 실행후에도 항상 돌아가는 프로그램을 만들어야 하는데 어떤 모듈을 쓸지 찾다가 python에서 apscheduler가 있다는 것을 알게 되었다. 다양한 스케줄러 중에서 대표적으로BlockingSchedulerBackgroundScheduler가 있다.

BackgroundScheduler 는 말그대로 백그라운드에서 실행된다.
해당 프로세스를 실행하면서 다른 프로세스도 계속해서 실행해야한다면 백그라운드스케줄러를 사용해야한다.

BlockingSscheduler는 단일 프로세스에 적합하므로 이번 포스팅에서는 BackgroundScheduler를 사용해보려 한다.

우선은 스케줄러 설치를 해주어야 한다.

pip install apscheduler

그후에 우리가 실행시켜주고 싶은 함수를 job 함수에 넣어고 main함수를 실행시켜 3초에 한번씩 job함수가 실행된다. 아래부분의 함수는 파일을 새로 만들어서 적어줘도 되고 아니면 기존 파일 안에 만들어줘도 된다.
api/cron.py

from apscheduler.schedulers.background import BackgroundScheduler

def job(data):
    print("----------")


def main():
    sched = BackgroundScheduler()
    sched.add_job(job,'interval', seconds=3, id='test')
    sched.start()

이 다음에 apps.py에 가서 Appconfig 코드를 변경해주어야 한다.

class ApiConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'api'
    def ready(self):
        from .cron import main
        main()

서버 실행 명령어

여기까지 다 작성했으면 이제 실행해보면 된다.

python manage.py runserver

서버는 잘 실행되지만 문제가 생겼다. 같은 동작을 두번이나 반복한다ㅜㅜ 구글링 해보면 서버실행할때 뒤에 옵션을 붙으면 정상 작동된다고 한다.

python manage.py runserver --noreload

위의 명령어로 해보니 아주 잘된다!! 여기까지 하면 이제 서버실행하면서 특정 함수를 계속 일정한 주기로 실행시킬 수 있다

실제 구현 코드

밑에는 실제 프로젝트에 쓰인 코드들이다. 이전 포스트들을 보면 건물의 위치 기반으로 날씨 데이터들을 저장하는 함수들을 구현했는데 최종적으로 그 함수를 서버 실행중에도 계속 30분 단위로 호출시켜 디비에 저장 시키기 위한 코드들이다.

def job():
    print(f'******{time.strftime("%H:%M:%S")}******')

    buildings = Building.objects.all()
    for building in buildings:
        nx, ny = mapToGrid(building.lat, building.lon)
        data = check_weather(nx, ny)
        weather, created = WeatherDB.objects.get_or_create(building=building)
        weather.temp = data['tmp']
        weather.humidity = data['hum']
        weather.rainType = data['rain']
        weather.sky = data['sky']
        weather.save()

    print("weatherDB saved")!
    print("************************")

def cron_weather():
    sched = BackgroundScheduler()
    # 30분마다 실행
    sched.add_job(job, 'interval', minutes=30, id='cron_weather')
    sched.start()

이 코드들을 실행해보면 아래와 같이 터미널에 나온다.

좋은 웹페이지 즐겨찾기