Closed realchandan closed 7 months ago
Hi there! Did you already find the section of how to run aiomqtt alongside FastAPI in our docs? 🙂
In your example, the code loops infinitely through the async for message in client.messages:
part, which means that FastAPI can't start because the startup never finishes.
I'm afraid that's not the issue, because If I use create_task
, still it throws the same error. I have modified the code -
import os
import sys
if sys.platform.lower() == "win32" or os.name.lower() == "nt":
from asyncio import WindowsSelectorEventLoopPolicy, set_event_loop_policy
set_event_loop_policy(WindowsSelectorEventLoopPolicy())
import asyncio
import contextlib
import aiomqtt
import fastapi
async def listen(client):
async for message in client.messages:
print(message.payload)
client = None
@contextlib.asynccontextmanager
async def lifespan(app):
global client
async with aiomqtt.Client("test.mosquitto.org") as c:
# Make client globally available
client = c
# Listen for MQTT messages in (unawaited) asyncio task
await client.subscribe("humidity/#")
loop = asyncio.get_event_loop()
task = loop.create_task(listen(client))
yield
# Cancel the task
task.cancel()
# Wait for the task to be cancelled
try:
await task
except asyncio.CancelledError:
pass
app = fastapi.FastAPI(lifespan=lifespan)
@app.get("/")
async def publish():
await client.publish("humidity/outside", 0.38)
And when I do uvicorn main:app
, I get -
Exception in callback AbstractEventLoop.add_reader(800, <function Cli...002F5A9ECBD80>)
handle: <Handle AbstractEventLoop.add_reader(800, <function Cli...002F5A9ECBD80>)>
Traceback (most recent call last):
File "C:\Users\Chandan\AppData\Local\Programs\Python\Python311\Lib\asyncio\events.py", line 80, in _run
self._context.run(self._callback, *self._args)
File "C:\Users\Chandan\AppData\Local\Programs\Python\Python311\Lib\asyncio\events.py", line 530, in add_reader
raise NotImplementedError
NotImplementedError
Exception in callback AbstractEventLoop.add_writer(<socket.socke...93.94', 1883)>, <function Cli...002F5A9F398A0>)
handle: <Handle AbstractEventLoop.add_writer(<socket.socke...93.94', 1883)>, <function Cli...002F5A9F398A0>)>
Traceback (most recent call last):
File "C:\Users\Chandan\AppData\Local\Programs\Python\Python311\Lib\asyncio\events.py", line 80, in _run
self._context.run(self._callback, *self._args)
File "C:\Users\Chandan\AppData\Local\Programs\Python\Python311\Lib\asyncio\events.py", line 536, in add_writer
raise NotImplementedError
Which is weird because I have set the event loop to WindowsSelectorEventLoopPolicy
Ah, I think I understand what you mean now 👍
I haven't tested it, but I suspect what's happening is that in the case where you run uvicorn from the command line, uvicorn creates an event loop before the Windows-specific policy is set. aiomqtt then takes the already running event loop via get_event_loop
(where in the case that one doesn't already exists, it would create a new one) and thus ends up with a Windows-incompatible loop.
On the other hand, if you run python main.py
the policy is set before uvicorn.run()
is executed.
I know that you can pass an existing event loop to uvicorn programmatically, but I'm less sure that that's possible when you invoke it via the command line. If there's no option for that I fear there's no way around running it via python main.py
.
Let me know if that helps 🙂
Ah, Okay! I guess you are right, It has something to do with how uvicorn works, than this library, Anyways I have moved to using WSL now.
I'll close this then 🙂
I've written a very simple, reproducible script that demonstrates the error I'm facing. If I name the file
main.py
, I can run the file usingpython main.py
on Windows 10, and no error is thrown. However, if I try running it withuvicorn main:app
, it doesn't work.I'm not sure whether this repository is the right place, or if the uvicorn repo is where I should raise this issue. Can anyone give me any hints on how to get it to work with
uvicorn main:app
?