首页 > 解决方案 > 具有异步功能的装饰器

问题描述

我正在尝试在 python 中实现实时网络摄像头服务,所以我正在寻找 aiortc。查看GitHub 页面上的示例,我发现了一个陌生的东西,我无法理解它是如何工作的。

server/server.py示例文件夹上,有一个async带有装饰器的函数。该函数从未被调用,所以我无法理解装饰器是如何工作的。


    pc = RTCPeerConnection()
    
    .......

    @pc.on("iceconnectionstatechange")
    async def on_iceconnectionstatechange():
        log_info("ICE connection state is %s", pc.iceConnectionState)
        if pc.iceConnectionState == "failed":
            await pc.close()
            pcs.discard(pc)

在这种情况下,该函数on_iceconnectionstatechange永远不会被调用。以何种方式@pc.on调用装饰器?

标签: pythonasync-awaitpython-decorators

解决方案


RTCPeerConnection继承自AsyncIOEventEmitter( link ) 的pyee模块pyee是一个事件系统模块。这个AsyncIOEventEmitter类是on装饰器方法的来源。

on_iceconnectionstatechange函数永远不会被直接调用,但装饰器将其注册为事件侦听器,因此每当该事件发出时都会调用它,例如此处

由于装饰器的工作方式,问题中的代码片段大致相当于:

decorator = pc.on("iceconnectionstatechange")

async def on_iceconnectionstatechange():
    log_info("ICE connection state is %s", pc.iceConnectionState)
    if pc.iceConnectionState == "failed":
        await pc.close()
        pcs.discard(pc)

on_iceconnectionstatechange = decorator(on_iceconnectionstatechange)

这是decorator(来自此处)的“定义”的片段:

def _on(f):
    self._add_event_handler(event, f, f)
    return f

这里, 的值为event"iceconnectionstatechange"所以代码等价于:

async def on_iceconnectionstatechange():
    log_info("ICE connection state is %s", pc.iceConnectionState)
    if pc.iceConnectionState == "failed":
        await pc.close()
        pcs.discard(pc)

pc._add_event_handler("iceconnectionstatechange", on_iceconnectionstatechange, on_iceconnectionstatechange)

因为该decorator函数被调用,所以它可以on_iceconnectionstatechange在一些内部字典中注册,以便在发出相关事件时调用它。装饰器注册事件监听器而不on_iceconnectionstatechange被直接调用,因为它在创建时注册它,而不是等待它被调用。


推荐阅读