二十九 Home Assistant 异步操作

注意............
在较新版本中很网络请求不使用异步,都会报错

异步操作

尽管我们有向后兼容的API,但直接使用异步核心会快得多。大多数核心组件已经被重写以利用异步核心。这包括 EntityComponent 助手(灯光、开关等的基础)、脚本、组和自动化。

与核心交互

Home Assistant核心中的所有方法都有两种实现方式:异步版本和可从其他线程调用的版本。其他线程版本仅仅是使用可用的异步工具以线程安全的方式调用异步版本的包装器。

所以,如果你从回调函数或协程中调用核心(hass 对象),请使用以 async_ 开头的方法。如果你需要调用一个是协程的 async_ 函数,你的任务也必须是协程。

实现异步组件

要使一个组件成为异步的,实现 async_setup

def setup(hass, config):
    # 在事件循环外设置你的组件。

将变为:

import asyncio

@asyncio.coroutine
def async_setup(hass, config):
    # 在事件循环内设置你的组件。

实现异步平台

对于平台,我们支持异步设置。你需要有一个协程 async_setup_platform,而不是 setup_platform

setup_platform(hass, config, add_entities, discovery_info=None):
    # 在事件循环外设置你的平台。

将变为:

import asyncio

@asyncio.coroutine
def async_setup_platform(hass, config, async_add_entities,
                         discovery_info=None):
    # 在事件循环内设置你的平台

与原始参数的唯一区别是 add_entities 函数已被异步友好的回调函数 async_add_entities 取代。

实现异步实体

你可以通过将你的 update 方法转换为异步来使你的实体支持异步。这要求你的实体的依赖项也支持异步!

class MyEntity(Entity):
    def update(self):
        """获取最新状态。"""
        self._state = fetch_state()

将变为:

import asyncio

class MyEntity(Entity):
    @asyncio.coroutine
    def async_update(self):
        """获取最新状态。"""
        self._state = yield from async_fetch_state()

确保在你的实体上定义的所有属性不会导致进行I/O操作。所有数据必须在 update 方法内获取并缓存在实体上。这是因为这些属性是在事件循环内读取的,因此进行I/O操作将导致Home Assistant核心等待,直到你的I/O操作完成。

从线程调用异步函数

有时你会在一个线程中,并且想要调用一个仅作为异步函数可用的函数。Home Assistant包含一些异步帮助工具来处理这种情况。

在下面的例子中,say_hello 将调度 async_say_hello 并阻塞,直到函数运行并返回结果。

from homeassistant.util.async import run_callback_threadsafe

def say_hello(hass, target):
    return run_callback_threadsafe(
        hass.loop, async_say_hello, target).result()

def async_say_hello(hass, target):
    return "Hello {}!".format(target)

处理传入的函数

如果你的代码接受来自其他代码的函数,你将不知道该函数属于哪个类别以及应该如何调用它们。这通常只发生在你的代码提供像 mqtt.async_subscribetrack_state_change_listener 这样的事件助手时。

为了帮助处理这种情况,hass 对象上有两个帮助方法,你可以在事件循环内调用它们:

hass.async_run_job

如果函数应该尽快被调用,则使用此方法。这将立即调用回调函数,将协程调度到事件循环上执行,并将其他函数调度到线程池中运行。

函数类型行为
回调函数立即调用。
协程调度到事件循环上执行。
其他函数调度到线程池中执行。
hass.async_add_job

如果函数应该被调用,但不优先于已调度的调用,则使用此方法。

函数类型行为
回调函数调度到事件循环上执行。
协程调度到事件循环上执行。
其他函数调度到线程池中执行。

杂项异步

关于 async 和 await 语法呢?
Python 3.5 引入了新的语法来规范异步模式。然而,这与 Python 3.4 不兼容。Home Assistant 所需的最低 Python 版本基于 Debian 稳定版附带的 Python 版本,目前是 3.4.2。

总结

在Home Assistant中如何使用异步功能。包括与核心交互时应根据情况选择合适的方法(异步或非异步版本);实现异步组件、平台和实体的方法,如通过定义 async_setupasync_setup_platform 和将实体的 update 方法转为异步等;从线程调用异步函数可借助 run_callback_threadsafe 工具;处理传入函数时可利用 hass 对象的 async_run_jobasync_add_job 方法,它们能根据函数类型将其正确调度到相应位置执行,帮助开发者更好地在Home Assistant中运用异步编程,提升程序性能和效率。
Python 3.5 引入的新语法 “async” 和 “await” 用于规范异步模式,但 Home Assistant 基于 Debian 稳定版的 Python 3.4.2,该语法与之不兼容。同时对 Brett Cannon 在异步语法和编程原理解析方面表示了感谢,

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值