You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在asyncio应用中正确使用Python zeroconf?

解决asyncio环境下Python zeroconf的RuntimeError问题

在asyncio应用中使用zeroconf时,原代码里的同步回调函数调用zeroconf.get_service_info()触发了以下错误:

RuntimeError: Use AsyncServiceInfo.async_request from the event loop

原代码示例:

import asyncio
from zeroconf import Zeroconf, ServiceStateChange
from zeroconf.asyncio import AsyncServiceBrowser

def on_service_state_change(zeroconf, service_type, name, state_change):
    if state_change == ServiceStateChange.Added:
        info = zeroconf.get_service_info(service_type, name)
        print(info)

async def browse_services():
    zeroconf = Zeroconf()
    service_type = "_http._tcp.local."

    browser = AsyncServiceBrowser(zeroconf, service_type, handlers=[on_service_state_change])

    try:
        await asyncio.Event().wait()
    finally:
        zeroconf.close()

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

正确实现方式

核心问题是异步环境下不能使用zeroconf的同步API,同时回调函数需要适配异步逻辑。修正后的实现如下:

  1. 使用AsyncZeroconf替代同步的Zeroconf,适配asyncio事件循环
  2. 将回调函数改为异步函数,内部使用异步API获取服务信息
  3. 借助async with自动管理AsyncZeroconf的资源释放

完整修正代码:

import asyncio
from zeroconf import ServiceStateChange
from zeroconf.asyncio import AsyncServiceBrowser, AsyncZeroconf

async def handle_service_change(zeroconf: AsyncZeroconf, service_type, name, state_change):
    if state_change == ServiceStateChange.Added:
        # 使用异步API获取服务信息
        info = await zeroconf.async_get_service_info(service_type, name)
        print(f"发现服务:{info}")

async def browse_services():
    # 用AsyncZeroconf替代同步Zeroconf,配合async with自动释放资源
    async with AsyncZeroconf() as zeroconf:
        service_type = "_http._tcp.local."
        # 传入异步回调函数,zeroconf会自动在事件循环中调度执行
        browser = AsyncServiceBrowser(zeroconf, service_type, handlers=[handle_service_change])
        # 保持事件循环持续运行
        await asyncio.Event().wait()

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

关键修改说明

  • AsyncZeroconf:异步版本的核心实例,提供所有异步操作API,避免同步API在事件循环中引发阻塞或错误
  • 异步回调:zeroconf的异步浏览器支持接收异步回调函数,会自动将其包装为asyncio任务调度执行,无需手动调用asyncio.create_task
  • 资源管理:async with语法自动处理AsyncZeroconf的初始化和关闭,替代手动调用close()的繁琐操作

内容的提问来源于stack exchange,提问作者Tom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 00:57:03