[英]Python non-blocking input
我有一个应用程序,它必须每 4 秒向我的 API 发出一次获取请求才能保持授权。 我的问题是,它使用了大量的input()
来阻塞线程来发出请求。 我试图编写一个完整的模块来解决这个问题,但它仍然处于阻塞状态。 我花了很长时间试图获得非阻塞输入。 我已经尝试了几乎所有的 SO。 这是我为非阻塞输入编写的类。 (它有一个函数nbput()
几乎完全像 python 的input()
)
from pynput import keyboard
from pynput.keyboard import Key
import threading
import sys
from functools import partial
uinput = ''
lastKey = ''
modifierKey = ''
class NonBlockingInput:
arg0 = ''
def __init__(self):
global listener
listener = keyboard.Listener(on_press=self.on_press, on_release=self.on_release)
print('1')
def on_press(self, key):
global lastKey
global modifierKey
try:
sys.stdout.write(key.char)
lastKey = key.char
except AttributeError:
if key == Key.space:
lastKey = ' '
sys.stdout.write(' ')
return
modifierKey = key
def on_release(self, key):
pass
def nbinput(self, prompt):
global uinput
global listener
global lastKey
global modifierKey
global arg0
listener.start()
sys.stdout.write(prompt)
while True:
if modifierKey == Key.enter:
sys.stdout.write('\n')
value_returned = partial(self.retrieved_data_func, arg0)
break
elif modifierKey == Key.backspace:
spaceString = ''
for _ in range(0, len(uinput)):
spaceString += ' '
uinput = uinput[:-1]
sys.stdout.write('\r')
sys.stdout.write(spaceString)
sys.stdout.write('\r')
sys.stdout.write(uinput)
modifierKey = ''
else:
uinput += lastKey
lastKey = ''
def retrieved_data_func(self):
arg0 = 0
return arg0
def nbput(prompt=''):
global collectionThread
nonBlockingInput = NonBlockingInput()
collectionThread = threading.Thread(nonBlockingInput.nbinput(prompt))
collectionThread.start()
return NonBlockingInput.retrieved_data_func()
if __name__ == '__main__':
print(nbput())```
所有这些管道似乎都妨碍了一些不那么复杂的事情:
from time import sleep
from pynput import keyboard
def key_press(key):
print(f'Pressed {key}')
def api_call():
print('Making API call...')
listener = keyboard.Listener(on_press=key_press)
listener.start()
while True:
api_call()
sleep(4)
该脚本每 4 秒“调用一次 API”,同时处理传入的用户输入。它使用pyinput
,因此它应该可以在您使用的任何平台上运行。
由于此处的“API 调用”只是一个打印语句,因此不需要任何花哨的东西,但您当然也可以异步进行调用。 sleep(4)
只是用来模拟 4 秒的阻塞活动。
您回答说您希望将所有内容都放在一个类中,这在避免全局变量方面是有道理的,但它不是您想要多次(甚至一次)实例化的类。
这是一个示例,它似乎可以在避免一些复杂性的同时做您想做的事情:
import sys
from time import sleep
from pynput import keyboard
import winsound
try:
import msvcrt
except ImportError:
msvcrt = None
import termios
class NBI:
text = ''
listener = None
@classmethod
def start(cls):
if cls.listener is None:
cls.listener = keyboard.Listener(on_press=cls.key_press)
cls.listener.start()
else:
raise Exception('Cannot start NBI twice.')
@staticmethod
def flush_input():
if msvcrt is not None:
while msvcrt.kbhit():
msvcrt.getch()
else:
termios.tcflush(sys.stdin, termios.TCIOFLUSH)
@classmethod
def key_press(cls, key):
if key == keyboard.Key.enter:
sys.stdout.write('\n')
cls.flush_input()
cls.listener.stop()
cls.listener = None
if key == keyboard.Key.backspace:
cls.text = cls.text[:-1]
sys.stdout.write('\b \b')
sys.stdout.flush()
elif hasattr(key, 'char'):
cls.text += key.char
sys.stdout.write(key.char)
sys.stdout.flush()
cls.flush_input()
def api_call():
winsound.Beep(440, 200) # "API call"
NBI.start()
while NBI.listener:
api_call()
for _ in range(4):
sleep(1)
if not NBI.listener:
break
print(f'You entered: {NBI.text}')
我找到了解决方案:我创建了 authThread,然后调用 main.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.