[英]Python3: detect keypresses asynchronously and communicate them to the main thread
免责声明 :import语句在函数内,我知道这很罕见。 我在这里展示我的整个程序,是在讲述我的问题和想法的同时,逐个功能地展示它。 实际上,我在做一些不同的事情,我只是为这个Stackoverflow问题做了一个最小的例子。 有重复的问题,但是我没有在其中找到好的答案,因为那些人只说“使用多线程”(例如, 此答案 )。 这个特定问题与如何使用多线程有关。
故事 :我正在用Python运行程序。 假设这是一个进入无限循环的while循环。 它只是运行愉快。 例如,
def job(threadname, q):
from time import sleep
c = 0
while True:
sleep(0.1) #slow the loop down
c += 1
print(c)
我想要做的是,它异步检测到stdin
上的按键,然后中断执行,这样我就可以在被中断的函数中执行我想做的任何事情(或者如果我正在使用python3 -i program.py
运行它) python3 -i program.py
,要在加载了我所有模块的情况下切换到REPL,请记住这是一个最小的示例,在该示例中,我不想过多强调此类问题。
我的想法是:我有一个函数可以异步获取按键,然后通过队列将其发送到另一个线程,然后它可以工作。 因此,我将工作职能扩展为:
def job(threadname, q):
from time import sleep
c = 0
while True:
sleep(0.1) #slow the loop down
c += 1
print(c)
ch = q.get() #extension for multithreading
handle_keypress(ch) #extension for handling keypresses
handle_keypress(ch)
的代码是:
def handle_keypress(key):
if (key == "q"):
print("Quit thread")
exit(0)
elif (key == "s"):
print("would you like to change the step size? This has not been implemented yet.")
else:
print("you pressed another key, how nice! Unfortunately, there are not anymore options available yet.")
换句话说,除了展示我希望能够做到这一点之外,没有那么有趣。
最初,问题似乎出在job()
函数中。 罪魁祸首是q.get()
,它正在挂起。 但是,它挂起是因为我的输入线程出于某种原因不是异步的并且阻塞了。 我不知道如何使其畅通无阻。
这是我的输入线程的功能:
def get_input(threadname, q):
#get one character, this code is adapted from https://stackoverflow.com/questions/510357/python-read-a-single-character-from-the-user
while True:
import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
q.put(ch)
对我来说很明显sys.stdin.read(1)
正在阻止,但我不知道如何使其不受阻碍。 在现在的状态下,我也想不出一种处理毒丸情况的方法,这就是为什么job()
函数中的q.get()
被阻止的原因。
我通过调用以下函数来运行程序:
def run_program():
from threading import Thread
from queue import Queue
queue = Queue()
thread1 = Thread( target=get_input, args=("Thread-1", queue) )
thread2 = Thread( target=job, args=("Thread-2", queue) )
thread1.start()
thread2.start()
thread1.join()
thread2.join()
我的问题 :这是您如何设计一个程序来处理异步按键吗? 如果是这样,如何使get_input()
函数不受get_input()
?
多亏了Sav,我找到了回答这个问题的方法。 我认为,他的评论就是答案。 因此,如果他将重写他的评论。 我接受他的回答。 现在,我将展示为了使非阻塞实现正常工作而更改的代码部分:
def job(threadname, q):
from queue import Empty
from time import sleep
c = 0
while True:
sleep(0.1) #slow the loop down
c += 1
print(c)
#Below is the changed part
ch = None
try:
ch = q.get(block=False)
except Empty:
pass
if ch is not None:
handle_keypress(ch)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.