kas*_*bah 5 python python-3.x python-asyncio
我正在尝试将这个关键的“去抖动”逻辑从 Javascript 翻译为 Python。
function handle_key(key) {
if (this.state == null) {
this.state = ''
}
this.state += key
clearTimeout(this.timeout)
this.timeout = setTimeout(() => {
console.log(this.state)
}, 500)
}
handle_key('a')
handle_key('b')
Run Code Online (Sandbox Code Playgroud)
这个想法是随后的按键会延长超时时间。Javascript 版本打印:
ab
Run Code Online (Sandbox Code Playgroud)
我不想翻译 JS 超时函数,我宁愿使用惯用的 Python 使用 asyncio。我在 Python (3.5) 中的尝试如下,但它不起作用,因为它global_state实际上没有按我的预期更新。
import asyncio
global_state = ''
@asyncio.coroutine
def handle_key(key):
global global_state
global_state += key
local_state = global_state
yield from asyncio.sleep(0.5)
#if another call hasn't modified global_state we print it
if local_state == global_state:
print(global_state)
@asyncio.coroutine
def main():
yield from handle_key('a')
yield from handle_key('b')
ioloop = asyncio.get_event_loop()
ioloop.run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)
它打印:
a
ab
Run Code Online (Sandbox Code Playgroud)
我已经研究过 asyncio Event,Queue但Condition我不清楚如何使用它们来实现此目的。如何使用 Python 的 asyncio 实现所需的行为?
编辑
有关我想如何使用的更多详细信息handle_keys。我有一个异步函数来检查按键。
@asyncio.coroutine
def check_keys():
keys = driver.get_keys()
for key in keys:
yield from handle_key(key)
Run Code Online (Sandbox Code Playgroud)
这又与其他程序任务一起安排
@asyncio.coroutine
def main():
while True:
yield from check_keys()
yield from do_other_stuff()
ioloop = asyncio.get_event_loop()
ioloop.run_until_complete(main())
Run Code Online (Sandbox Code Playgroud)
asyncio.create_taskQeek 对and的使用asyncio.gather是有道理的。但我该如何在这样的循环中使用它呢?或者是否有另一种方法来安排允许调用“重叠”的异步任务handle_keys?
基本上yield from xy()与正常的函数调用非常相似。函数调用和函数调用的区别yield from在于,函数调用立即开始处理被调用的函数。该yield from语句将调用的协程插入事件循环内的队列中,并将控制权交给事件循环,并决定将处理队列中的哪个协程。
以下是您的代码的作用的解释:
main到事件循环的队列中。main协程,因此它会启动它。yield from handle_key('a').handle_key('a')到事件循环的队列中。mainandhandle_key('a')但 main 无法启动,因为它正在等待 的结果handle_key('a')。handle_key('a').yield from asyncio.sleep(0.5)。main(),handle_key('a')和sleep(0.5)。
main()等待 的结果handle_key('a')。handle_key('a')等待 的结果sleep(0.5)。asyncio.sleep(0.5)返回。NoneNone并将其返回到handle_key('a')协程中。handle_key('a')密钥(因为状态没有改变)handle_key程返回 None (因为没有 return 语句)。None到主程序。yield from handle_key('b')并开始处理新的键。b)。coroutinrmain替换为:
@asyncio.coroutine
def main(loop=asyncio.get_event_loop()):
a_task = loop.create_task(handle_key('a'))
b_task = loop.create_task(handle_key('b'))
yield from asyncio.gather(a_task, b_task)
Run Code Online (Sandbox Code Playgroud)
将其loop.create_task添加到事件循环的队列中,然后handle_key('a')将控制权交给事件循环。从此时开始的事件循环包含、、和。handle_key('b')yield from asyncio.gather(a_task, b_task)handle_key('a')handle_key('b')gather(...)main()
main()结果来自gather()gather()所有作为参数给出的任务完成handle_key('a')。handle_key('b')事件循环现在包含 2 个可以启动的协程,但它会选择哪一个呢?嗯...谁知道这取决于实施。因此,为了更好地模拟按键,这个替换应该更好一点:
@asyncio.coroutine
def main(loop=asyncio.get_event_loop()):
a_task = loop.create_task(handle_key('a'))
yield from asyncio.sleep(0.1)
b_task = loop.create_task(handle_key('b'))
yield from asyncio.gather(a_task, b_task)
Run Code Online (Sandbox Code Playgroud)
从文档中:
与 asyncio 一起使用的协程可以使用 async def 语句来实现。
async def 类型的协程是在 Python 3.5 中添加的,如果不需要支持较旧的 Python 版本,建议使用。
这意味着您可以替换:
@asyncio.coroutine
def main():
Run Code Online (Sandbox Code Playgroud)
与较新的声明
async def main():
Run Code Online (Sandbox Code Playgroud)
如果您开始使用新语法,那么您还必须替换yield from为await.
| 归档时间: |
|
| 查看次数: |
4531 次 |
| 最近记录: |