Hello,
I've started using python-zeroconf in an async project, and would like to ask whether it could be made possible for the ServiceListener callbacks (add_service, update_service and remove_service) to be async coroutines instead of sync functions.
To illustrate I've rewritten the service browser example in the Readme using async methods. Note that async_add_service_listener() along with async with really tidy up the main loop, but the sync-async friction makes the ServiceListener a bit messy (plus need to handle the AsyncZeroconf object separately).
(A related question linked to this example: which thread executes the ServiceListener callbacks? Should I be using asyncio.create_task() or asyncio.run_coroutine_threadsafe()?)
Async MWE of service browser in readme
import asyncio, sys
from zeroconf import ServiceListener, Zeroconf
from zeroconf.asyncio import AsyncZeroconf
SERVICE_TYPE = "_http._tcp.local."
class MyListener(ServiceListener):
def __init__(self, aiozc: AsyncZeroconf):
self.aiozc = aiozc
def update_service(self, zc: Zeroconf, type_: str, name: str) -> None:
print(f"Service {name} updated")
def remove_service(self, zc: Zeroconf, type_: str, name: str) -> None:
print(f"Service {name} removed")
def add_service(self, zc: Zeroconf, type_: str, name: str) -> None:
# Should this be asyncio.run_coroutine_threadsafe() for thread safety?
asyncio.create_task(self.async_add_service(zc, type_, name))
async def async_add_service(self, zc: Zeroconf, type_: str, name: str) -> None:
info = await self.aiozc.async_get_service_info(type_, name)
print(f"Service {name} added, service info: {info}")
async def get_all_services():
async with AsyncZeroconf() as aiozc:
listener = MyListener(aiozc)
await aiozc.async_add_service_listener(SERVICE_TYPE, listener)
while True:
await asyncio.sleep(10)
try:
print("Press Ctrl-C to exit...\n")
asyncio.run(get_all_services())
except KeyboardInterrupt:
sys.exit()
It would be much nicer to be able to do the following instead, perhaps via an AsyncServiceListener class:
class MyAsyncListener(AsyncServiceListener):
async def async_update_service(self, aiozc: AsyncZeroconf, type_: str, name: str) -> None:
print(f"Service {name} updated")
async def async_remove_service(self, aiozc: AsyncZeroconf, type_: str, name: str) -> None:
print(f"Service {name} removed")
async def async_add_service(self, aiozc: AsyncZeroconf, type_: str, name: str) -> None:
info = await aiozc.async_get_service_info(type_, name)
print(f"Service {name} added, service info: {info}")
async def get_all_services():
async with AsyncZeroconf() as aiozc:
listener = MyAsyncListener()
await aiozc.async_add_service_listener(SERVICE_TYPE, listener)
while True:
await asyncio.sleep(10)
What do others think? Is there a better way to achieve what I'm after?
Thanks,
Dan.
P.S. Thank you to everyone who's put time into this project!
Hello,
I've started using python-zeroconf in an async project, and would like to ask whether it could be made possible for the
ServiceListenercallbacks (add_service,update_serviceandremove_service) to be async coroutines instead of sync functions.To illustrate I've rewritten the service browser example in the Readme using async methods. Note that
async_add_service_listener()along withasync withreally tidy up the main loop, but the sync-async friction makes theServiceListenera bit messy (plus need to handle theAsyncZeroconfobject separately).(A related question linked to this example: which thread executes the
ServiceListenercallbacks? Should I be usingasyncio.create_task()orasyncio.run_coroutine_threadsafe()?)Async MWE of service browser in readme
It would be much nicer to be able to do the following instead, perhaps via an
AsyncServiceListenerclass:What do others think? Is there a better way to achieve what I'm after?
Thanks,
Dan.
P.S. Thank you to everyone who's put time into this project!