理解线程与阻止键盘监听器的结合

时间:2018-10-18 15:38:21

标签: python multithreading

我试图实现的是一个超时倒数,可以通过pynput键事件来中断。

在我的第一个实现中,有一个错误:我看不到告诉Pynput线程超时已结束的可能性。

根据Python threading文档,我需要创建一个更复杂的 Condition 对象,还是某种同步线程?还是我想扩展原始的Pynput类?

对于我来说,在这种情况下很难理解哪个线程是生产者还是消费者

代码。

模块代码

import threading
import time
from pynput import keyboard
import subprocess

class CountdownWithInterrupt:
    """A countdown feature which user can interrupt by pressing Enter key"""
    def __init__(self, interval, message="Press enter to continue..."):
        """Constructor"""
        self.window_id = self.obtain_window_id()
        self.interrupt_key = keyboard.Key.enter
        self.message = message
        self.user_pressed_key = False
        self.timeout_over = False
        self.timer_thread = threading.Thread(name='timer',
                                             target=self.timer,
                                             kwargs={"interval":interval})
        self.kblistener_thread = threading.Thread(name='keyboard_listener',
                                                  target=self.keyboard_listener)

    def obtain_window_id(self):
    """Ignore keyboard events if they come from other windows"""
        try:
            result = subprocess.run(['xdotool', 'getactivewindow'], stdout=subprocess.PIPE)
            window_id = result.stdout
        except DisplayNameError:
            window_id = print (random.randint(1,21)*5)

        return window_id

    def lock(self):
        return self.user_pressed_key or self.timeout_over

    def start(self):
        """starts countdown"""
        print(self.message)
        self.timer_thread.start()
        self.kblistener_thread.start()


    def on_release(self, key):
        """listener action"""
        if (self.window_id != self.obtain_window_id()):
            return True
        if key == self.interrupt_key:
            # Stop listener
            self.user_pressed_key = True
            return False

        return True

    def keyboard_listener(self):
        """listen for interrupt"""
        with keyboard.Listener(on_release=self.on_release) as listener:
            listener.join()

    def timer(self, interval):
        """set up the resource to be used by the consumer"""
        time_left = interval
        while time_left > 0:
            if self.user_pressed_key:
                break
            print(time_left, end='\r', flush=True)
            time.sleep(1)
            time_left = time_left - 1
        self.timeout_over = True

实际程序

from modules.helpers import CountdownWithInterrupt

msg =  ("Press enter..")
interruptableCountdown = CountdownWithInterrupt(5, msg)
interruptableCountdown.start()
while(interruptableCountdown.lock() == False):
    pass
print("tuut!")

1 个答案:

答案 0 :(得分:0)

listener.stop()为我工作。