繁体   English   中英

Python非阻塞输入

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM