Skip to content
Advertisement

How to async handle callback from keyboard hotkeys?

Need to register global hotkeys. For example, f4 and f8. With keyboard library while first callback didn’t return, the next won’t call.

Another words, logs like this

JavaScript

But I want to like this

JavaScript

Demo code

JavaScript

I tried to use asyncio, but nothing changed

JavaScript
JavaScript

Update 1

Keyboard library’s developer gave advise to use call_later function that create new thread for each callback and it’s works like I want.

But is there way to do such task in the same thread (use asyncio)? I didn’t succeed.

JavaScript

Update 2

Now it’s look like below (full code on github). I seems that creating new threads in order to wait http request is too heavy operation. Thus I want to use asyncio in current thread and the same time continue handle other hotkeys.

JavaScript

Advertisement

Answer

Unfortunately none of the libraries you are using are actually awaitable, so using them with asyncio is going to be a challenge. You could extract the actual http calls from the google library and then implement your own client later using an asyncio-compatible library, but that’s a lot of work just to avoid the expense of spinning up a new thread.

Fortunately there’s already a way to avoid the expensive of spinning up threads: use a pool of worker threads. In this approach, rather than spinning up a new thread immediately for every callback, we add the task to a queue of tasks serviced by a pool of threads we spin up in advance. That way we pay to spin the thread up only one, and after that we only pay to serialise the request to the thread—which is not nothing, but it’s less than spinning up a thread.

Whilst it’s possible to have asyncio manage the thread pool, in this instance it brings no advantages at all, since nothing else in your code is awaitable. (If you did want to do this, you’d use loop.run_in_exeuctor(), taking care not to re-create the pool as noted in this question.)

Here’s some dummy code, which would need adapting to your classes:

JavaScript

There are other approaches, but I think writing it explicitly is clearer here. Note that I have assumed your code is not cpu-bound, so it makes sense to use threads rather than processes.

Incidentally, this looks very like a minimal implementation of something like celery, which is probably overkill for your needs but might we interesting to look at all the same.

BTW, I don’t read russian, but this looks like a fun project.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement