Python FASTAPI shedule task

Question:

I want to write a task that will only run once a day at 3:30 p.m. with Python FASTAPI. How can I do it?

I tried this but it works all the time.

schedule.every().day.at("15:30:00").do(job2)

while True:
    schedule.run_all()
Asked By: Arzu Yıldız

||

Answers:

Swap the schedule.run_all() for schedule.run_pending(). It should work!

import schedule
import time

def job():
    print("I'm working...")

schedule.every().day.at("15:30:00").do(job)

while True:
    schedule.run_pending()
Answered By: Leonardo Lima

Here is how you can do it with Rocketry. Rocketry is a statement-based scheduler and it integrates well with FastAPI.

Let’s say you have a scheduler.py. This is where you put your tasks. Content of this file:

from rocketry import Rocketry
from rocketry.conds import daily

app = Rocketry()

# Create some tasks:

@app.task(daily.after("15:30"))
def do_things():
    ...

Then the FastAPI app, let’s call this api.py:

from fastapi import FastAPI
from scheduler import app as app_rocketry

app = FastAPI()
session = app_rocketry.session

# Create some routes:

@app.get("/my-route")
async def get_tasks():
    # We can modify/read the Rocketry's runtime session
    return session.tasks

@app.post("/my-route")
async def manipulate_session():
    for task in session.tasks:
        ...

And then the main.py which combines these two and runs them both:

import asyncio
import uvicorn

from api import app as app_fastapi
from scheduler import app as app_rocketry

class Server(uvicorn.Server):
    """Customized uvicorn.Server

    Uvicorn server overrides signals and we need to include
    Rocketry to the signals."""
    def handle_exit(self, sig: int, frame) -> None:
        app_rocketry.session.shut_down()
        return super().handle_exit(sig, frame)


async def main():
    "Run scheduler and the API"
    server = Server(config=uvicorn.Config(app_fastapi, workers=1, loop="asyncio"))

    api = asyncio.create_task(server.serve())
    sched = asyncio.create_task(app_rocketry.serve())

    await asyncio.wait([sched, api])

if __name__ == "__main__":
    asyncio.run(main())

The two applications can seamlessly communicate with each other. I also made a template which you can just clone: https://github.com/Miksus/rocketry-with-fastapi

Relevant links:

Answered By: miksus
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.