Conditional in a coroutine based on whether it was called again?

Viewed 3330

I am trying to translate this key "debouncing" logic from Javascript to 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')

The idea is that subsequent key presses extend the timeout. The Javascript version prints:

ab 

I don't want to translate the JS timeout functions, I'd rather have idiomatic Python using asyncio. My attempt in Python (3.5) is below, but it doesn't work as global_state is not actually updated when I expect.

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())

It prints:

a
ab

I have looked into asyncio Event, Queue and Condition but it isn't clear to me how to use them for this. How would you implement the desired behavior using Python's asyncio?

EDIT

Some more details on how I'd like to use handle_keys. I have an async function that checks for key presses.

@asyncio.coroutine
def check_keys():
    keys = driver.get_keys()
    for key in keys:
        yield from handle_key(key)

Which in turn is scheduled along with other program tasks

@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())

Qeek's use of asyncio.create_task and asyncio.gather makes sense. But how would I use it within a loop like this? Or is there another way to schedule the async tasks that would allow handle_keys calls to "overlap"?

Actual code on GitHub if you are interested.

2 Answers
Related