Asyncio running multiple asynconrous functions at once with uvicorn and fastapi
Question:
I’m having some problems with running my own async functions with uvicorn (fastapi)
My goal is to be able to run the queue manager
function, as well as the uvicorn webapp. However, it seems that my start
function blocks the uvicorn.run
code from running.
async def queue_manager(self):
while True:
job = await self.queue.get()
print(job)
await asyncio.sleep(2)
async def start():
task1 = asyncio.create_task(queue_manager())
await asyncio.gather(task1)
app = FastAPI()
app.include_router(server.router)
if __name__ == "__main__":
asyncio.run(start())
uvicorn.run("main:app", host="0.0.0.0", port=5959)
In order to fix this I attempted to run uvicorn.run
inside of my start
function, however this results in the following error:
line 35, in <module>
asyncio.run(start())
line 17, in start
await uvicorn.run("main:app", host="0.0.0.0", port=5959)
RuntimeError: asyncio.run() cannot be called from a running event loop
async def start():
task1 = asyncio.create_task(custom_instance_manager.queue_manager())
task2 = asyncio.create_task(uvicorn.run(
"main:app", host="0.0.0.0", port=5959))
await asyncio.gather(task1, task2)
if __name__ == "__main__":
asyncio.run(start())
Answers:
You could use startup event.
async def queue_manager(self):
while True:
job = await self.queue.get()
print(job)
await asyncio.sleep(2)
app = FastAPI()
app.include_router(server.router)
@app.on_event('startup')
async def start():
asyncio.create_task(queue_manager())
if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", port=5959)
Instead of using uvicorn.run
you can use uvicorn server async func with fast api config
async def run_server():
api = configure_fastapi()
config = uvicorn.Config(api, port=8021, host='0.0.0.0')
server = uvicorn.Server(config)
await server.serve()
I’m having some problems with running my own async functions with uvicorn (fastapi)
My goal is to be able to run the queue manager
function, as well as the uvicorn webapp. However, it seems that my start
function blocks the uvicorn.run
code from running.
async def queue_manager(self):
while True:
job = await self.queue.get()
print(job)
await asyncio.sleep(2)
async def start():
task1 = asyncio.create_task(queue_manager())
await asyncio.gather(task1)
app = FastAPI()
app.include_router(server.router)
if __name__ == "__main__":
asyncio.run(start())
uvicorn.run("main:app", host="0.0.0.0", port=5959)
In order to fix this I attempted to run uvicorn.run
inside of my start
function, however this results in the following error:
line 35, in <module>
asyncio.run(start())
line 17, in start
await uvicorn.run("main:app", host="0.0.0.0", port=5959)
RuntimeError: asyncio.run() cannot be called from a running event loop
async def start():
task1 = asyncio.create_task(custom_instance_manager.queue_manager())
task2 = asyncio.create_task(uvicorn.run(
"main:app", host="0.0.0.0", port=5959))
await asyncio.gather(task1, task2)
if __name__ == "__main__":
asyncio.run(start())
You could use startup event.
async def queue_manager(self):
while True:
job = await self.queue.get()
print(job)
await asyncio.sleep(2)
app = FastAPI()
app.include_router(server.router)
@app.on_event('startup')
async def start():
asyncio.create_task(queue_manager())
if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", port=5959)
Instead of using uvicorn.run
you can use uvicorn server async func with fast api config
async def run_server():
api = configure_fastapi()
config = uvicorn.Config(api, port=8021, host='0.0.0.0')
server = uvicorn.Server(config)
await server.serve()