слушатель клавиатуры pynput вызывает задержки - PullRequest
0 голосов
/ 19 января 2020

Я делаю программу, которая включается и выключается определенной клавишей на клавиатуре (используя pynput). Я поместил слушатель клавиатуры l oop в первый поток, а действие l oop - во второй. Проблема в том, что после запуска кода он не сразу слушает клавиатуру, только через 9-10 секунд. И иногда он отказывается реагировать на кнопку Es c, а иногда работает. Как исправить отставание? Код в порядке?

from threading import Thread
from pynput import keyboard
import time

flag = False
kill = False

def on_press(key):
    global flag
    global kill

    if key == keyboard.KeyCode.from_char('a'):
        print('pressed A')
        flag = not flag
    if key == keyboard.Key.esc:
        kill = True
        return False

def thr2():
    print('joining...')
    with keyboard.Listener(on_press=on_press) as listen:
        listen.join()

def thr1():
    while True:
        if kill:
            break
        if flag:
            print('looping....')
            time.sleep(0.4)

if __name__ == "__main__":
    thread1 = Thread(target=thr1)
    thread2 = Thread(target=thr2)
    thread1.start()
    thread2.start()

Ответы [ 2 ]

1 голос
/ 19 января 2020

Похоже, что фактическая задержка исходит от клавиатуры pynput. Сам обработчик контекста прослушивателя. Я не могу сказать вам, что происходит под капотом, но задержка не связана с тем, как вы управляете своими потоками.

# pynput library creating keyboard.Listener thread causes the delay
with keyboard.Listener(on_press=on_press) as listen:  
    print('listen thread created')  # This does not happen until after the delay
    listen.join()

Возможно, вы захотите перефразировать вопрос так, чтобы он был определен c для ввода клавиатуры. Слушатель

0 голосов
/ 21 января 2020

Вот решение, которое прекрасно работает с многопроцессорностью:

import sys
from pynput import keyboard
from time import sleep
from multiprocessing import Process, Event
from functools import partial


def thr2(kill_event, flag_event):

    def on_press(kill_event, flag_event, key):
        if key == keyboard.KeyCode.from_char('a'):
            print('pressed A')
            if flag_event.is_set():
                flag_event.clear()
            else:
                flag_event.set()
        if key == keyboard.Key.esc:
            print('esc')
            kill_event.set()
            sys.exit(0)

    with keyboard.Listener(on_press=partial(on_press, kill_event, flag_event)) as listen:
        listen.join()


def thr1(kill_event, flag_event):
    while True:
        if kill_event.is_set():
            print('kill')
            sys.exit(0)
        if flag_event.is_set():
            print('looping....')
            sleep(0.4)


if __name__ == "__main__":
    kill_event = Event()
    flag_event = Event()

    thread1 = Process(target=thr1, args=(kill_event, flag_event))
    thread2 = Process(target=thr2, args=(kill_event, flag_event))

    thread1.start()
    thread2.start()

    thread1.join()  # Join processes here to avoid main process exit
    thread2.join()
...