python - 理解线程与阻塞键盘监听器的结合
问题描述
我尝试实现的是一个超时倒计时,它可以被一个pynput
关键事件打断。
在我的第一个实现中存在一个错误:我看不到告诉 pynput 线程超时结束的可能性。
根据 Python线程文档,我是否需要创建更复杂的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!")
解决方案
为我工作listener.stop()
。
推荐阅读
- python - 如何检查数字列表是否在python中的2个值之间?
- python - 如何将列表元素作为索引号在 Python 中打印另一个列表?
- java - recyclerView android上只能点击一项
- kubernetes - NetworkPolicy 无法限制来自 UI 的 Ingress
- javascript - 将条带结帐与 .net 集成
- node.js - 如何在 MERN 应用程序上使 Set-Cookie 警告消失?
- esp32 - 将 esp32 cam 连接到电脑
- html - 图像未调整的 HTML 链接
- sql-server - SQL Server:将 INSERT INTO SELECT 与具有相同源/目标数据库的 JOIN 一起使用时出现转换错误
- javascript - 为什么参数在函数中不可用