#๐Ÿ”’ How do i implement lifespan events | Fastapi

58 messages ยท Page 1 of 1 (latest)

bronze whale
#

I found out that startup and shutdown events are deprecated and want to switch over to lifespan events but dont understand the docs, can someone explain pls?

FastAPI framework, high performance, easy to learn, fast to code, ready for production

simple hornetBOT
#

@bronze whale

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

fallen spoke
#

what part do you not understand?

bronze whale
#

how would i implement them exactly, i understand the defining

#

but i have multiple events

#

do they get clubbed into 1

#

or how

fallen spoke
#

basically startup and shutdown are now combined into a single lifespan function

#

with a yield in between them

bronze whale
#

thats for 1 event sequence

fallen spoke
#

Do you have your current startup and shutdown events top hand?

bronze whale
#

what if i have multiple

bronze whale
fallen spoke
#

you'd call them all from within the lifespan function

fallen spoke
bronze whale
#
app.add_event_handler("startup", open_db) 
app.add_event_handler("startup", create_session)
app.add_event_handler("startup", add_new_parties) # called once every 5 seconds
app.add_event_handler("startup", check_for_inactivity) # called once every 5 seconds
app.add_event_handler("startup", update_party_details) # called once every 5 seconds
app.add_event_handler("startup", update_playback) # called once every 5 seconds

app.add_event_handler("shutdown", delete_parties)
app.add_event_handler("shutdown", close_db)
app.add_event_handler("shutdown", close_session)``` i have these
#

yes the code is ready

#

just want to switch over

fallen spoke
#

so instead do this ```py
from contextlib import asynccontextmanager

from fastapi import FastAPI

@asynccontextmanager
async def lifespan(app: FastAPI):
await open_db()
await create_session()
...etc...
yield
await delete_parties()
await close_db()
...

app = FastAPI(lifespan=lifespan)

#

changing the order as needed

bronze whale
#

im using fastapi_utils.tasks.repeat_every too so im unsure if they will work with context managers

fallen spoke
#

might be better to define a task that gets created on startup and repeats every 5s

bronze whale
fallen spoke
#

so instead do this ```py
import asyncio
from contextlib import asynccontextmanager

from fastapi import FastAPI

async def check_for_inactivity():
while True:
... do something
await asyncio.sleep(5)

@asynccontextmanager
async def lifespan(app: FastAPI):
asyncio.create_task(check_for_inactivity())
yield
await close_db()
...

app = FastAPI(lifespan=lifespan)

bronze whale
#

having a decorator is cleaner tho ๐Ÿ˜…

#
@repeat_every(seconds=5, raise_exceptions=True)
async def add_new_parties():
    parties = await get_parties()

    async for party in parties:
        if party["_id"] not in currently_listening.keys():
            currently_listening[party["_id"]] = party["party_info"]["users"]

fallen spoke
#

ah right, never used fastapi_utils, so not aware of that syntax

#

if it's rely on startup events to start the loop, then it needs to update to support the lifespan event

#

their docs might have more info

bronze whale
#

this is what im using

fallen spoke
#

oh, all the startup event does is call the task on startup too

#

so just call the function directly

#

If you also apply the @app.event("startup") decorator, FastAPI will call the function during server startup, and the function will then be called repeatedly while the server is still running.

fallen spoke
bronze whale
#

then it should be fine to use lifespan

fallen spoke
#

Yea

bronze whale
#

AttributeError: type object 'Database' has no attribute '__bool__'. Did you mean: '__call__'? it caused something

#

it was working fine before using lifespans

#

lemme get the code

fallen spoke
#

sure

#

!paste if it's long

simple hornetBOT
#
Pasting large amounts of code

If your code is too long to fit in a codeblock in Discord, you can paste your code here:
https://paste.pythondiscord.com/

After pasting your code, save it by clicking the Paste! button in the bottom left, or by pressing CTRL + S. After doing that, you will be navigated to the new paste's page. Copy the URL and post it here so others can see it.

bronze whale
#
from motor.motor_asyncio import AsyncIOMotorClient

async def open_db():
    global client, users_db, parties_db
    client = AsyncIOMotorClient(connection_str)
    users_db = client.users
    parties_db = client.parties
fallen spoke
#

what is Database from that error?

bronze whale
#
Traceback (most recent call last):
  File "d:\Python\SpartyTime\SpartyTime\backend\main.py", line 5, in <module>
    from routes import auth, parties
  File "d:\Python\SpartyTime\SpartyTime\backend\routes\auth.py", line 10, in <module>
    from utils.database_handler import create_user, get_user_by_id
  File "d:\Python\SpartyTime\SpartyTime\backend\utils\database_handler.py", line 6, in <module>
    from motor.motor_asyncio import AsyncIOMotorClient
  File "C:\Users\Sahran\AppData\Local\Programs\Python\Python311\Lib\site-packages\motor\motor_asyncio.py", line 46, in <module>
    AsyncIOMotorDatabase = create_asyncio_class(core.AgnosticDatabase)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Sahran\AppData\Local\Programs\Python\Python311\Lib\site-packages\motor\motor_asyncio.py", line 37, in create_asyncio_class
    return create_class_with_framework(cls, asyncio_framework, "motor.motor_asyncio")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Sahran\AppData\Local\Programs\Python\Python311\Lib\site-packages\motor\metaprogramming.py", line 293, in create_class_with_framework
    new_class_attr = attr.create_attribute(new_class, name)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Sahran\AppData\Local\Programs\Python\Python311\Lib\site-packages\motor\metaprogramming.py", line 228, in create_attribute
    return ReadOnlyProperty.create_attribute(self, cls, attr_name)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\Sahran\AppData\Local\Programs\Python\Python311\Lib\site-packages\motor\metaprogramming.py", line 206, in create_attribute
    doc = getattr(cls.__delegate_class__, attr_name).__doc__
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: type object 'Database' has no attribute '__bool__'. Did you mean: '__call__'?```
fallen spoke
#

seems to be failing on the import statement, rather than your code

bronze whale
#

but it was working just fine before lifespans

#

nvm

#

its still broken

#

okay updating the library fixed it

fallen spoke
#

nice

bronze whale
#

Thanks alot!

#

seems to be working fine

#

!close

simple hornetBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.