【问题标题】:pynput keyboard listener causes delayspynput 键盘侦听器导致延迟
【发布时间】:2020-05-05 12:50:30
【问题描述】:

我正在制作一个通过键盘上的某个键(使用 pynput)打开和关闭的程序。我将键盘侦听器循环放在第一个线程中,将动作循环放在第二个线程中。 问题是在我启动代码后,它并没有立即听键盘,只有在 9-10 秒过去了。有时它拒绝对 Esc 按钮做出反应,有时它会起作用。如何解决滞后?代码可以吗?

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

【问题讨论】:

    标签: python multithreading python-multithreading pynput


    【解决方案1】:

    看起来实际延迟来自 pynput keyboard.Listener 上下文处理程序本身。我无法告诉您幕后发生的事情,但延迟并非来自您管理线程的方式。

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

    您可能需要重新表述问题,以便它特定于 pynput keyboard.Listener

    【讨论】:

    • 你试过运行代码吗?你有同样的延迟吗?我注意到延迟不会发生,除非我将它放在线程下但是当我使用多处理并将 Thread(target=...) 更改为 Process(target=...) 时延迟消失了。但是我不能使用多处理,因为它由于某种原因无法识别全局变量,这就是我现在想要弄清楚的。您是否偶然知道如何在进程之间传递“标志”和“杀死”变量?
    • 我在线程内和线程外运行它时确实遇到了同样的延迟。它已经在线程中的事实并不重要,因为keyboard.Listen 处理程序无论如何都在创建一个新线程。使用多处理而不是线程会使事情变得困难,因为进程没有显式访问它们之外存在的任何内容。
    【解决方案2】:

    这是一个很好地与多处理配合使用的解决方案:

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

    【讨论】:

      猜你喜欢
      • 2021-02-11
      • 2019-04-04
      • 2021-11-15
      • 2020-11-03
      • 2020-05-24
      • 2022-01-02
      • 2020-12-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多