Python (желательно 3), эквивалентный INKEY$

Я использую Python 3.6.4 в системе Windows 7 (у меня есть другие системы, такие как Win 10 и Android, но это моя отправная точка).

INKEY$, для тех, кто не знаком с BASIC (почти любой разновидностью), представляет собой функцию, которая проверяет буфер клавиатуры, возвращает эти данные в виде строки или пустого значения (""), если данных не было, и очищает буфер. Длина возвращаемой строки зависит от данных в буфере, обычно 0, 1 или 2 по одному нажатию клавиши (раньше быстрая машинистка могла заполнить небольшой буфер между проверками). Клавиша Enter не была нужна (если только это не то, что вы искали) или не обрабатывалась, и программа не останавливалась, если только она не была запрограммирована на это.

Паузер:

    a$=""
    while a$=""
    a$=inkey$
    wend

Прерыватель потока:

    a=0
    while a < 1000
        a=a+1
        print a
        a$=inkey$
        if a$<>"" then exit while
    wend

Быстрый парсер:

    a$=inkey$
    if a$<>"" then
        rem process input
        rem like arrow keys/a w s z for directional movement
        rem useful for games and custom editors
    end if

Я хочу знать, есть ли в Python простая кросс-платформенная функция (т.е. не более 10 строк кода, если только в импортируемом модуле/классе), которая эквивалентна функции INKEY$? Кроме того, я не хочу импортировать игровой модуль (модули), мне просто нужен эквивалент функции INKEY$ (простой, прямолинейный, маленький).

    import inkey
    a = inkey.inkey()

Обновление № 1: после того, как я установил модуль readchar и исправил сообщенную ошибку Python (stdout.write(a) должен быть stdout.write(str(a)) так как переменная 'a', по-видимому, возвращается как байтовая строка из функции readchar()) при использовании кода, указанного г-ном Страттоном ниже, я получаю только непрерывный поток b'\xff' и эхо-символы консоли, если есть какие-либо нажатия клавиш.

Разборка его для использования только функции также не помогает:

    from readchar import readchar
    from sys import stdout
    import os

    #I like clear screens, and I can not lie
    os.system('cls')  # For Windows
    #os.system('clear')  # For Linux/OS X

    def inkey():
        "INKEY$ function"
        return readchar()
        #let the processing hit the floor, elsewhere

    b=0
    step = 1
    while b < 1000:
        b = b + step
        print(b)
        #convert bytes to integers
        a = int.from_bytes(inkey(), "big")
        #remember I keep getting b'\xff' (255) when buffer is empty
        if chr(a) == "a":
            step = step - 1
            a = 255 #don't stop
        if chr(a) == "l":
            step = step + 1
            a = 255 #don't stop
        if a != 255:
            break 

Предполагается считать b от 0 до 999, останавливаясь почти на любом нажатии клавиши, 'a' уменьшает шаг, 'l' увеличивает. Вместо этого он печатает нажатие клавиши либо до, либо после значения b в зависимости от времени и продолжается до тех пор, пока b = 1000. Ничего из того, что я сделал, не изменило ситуацию.

В то время как функцию Pauser можно заменить на input() (i = input("Нажмите клавишу Enter, чтобы продолжить")), другие два варианта не могут быть изменены так легко, как кажется.


person James V. Fields    schedule 28.03.2020    source источник


Ответы (1)


Ближе всего к тому, что вы ищете, вероятно, библиотека readchar.

Вот пример, напоминающий старую логику BASIC:

from readchar import readchar
from sys import stdout

a = ' '
while ord(a) not in [3,24,27]:
    a = readchar()
    stdout.write(a)
    stdout.flush()
    if ord(a) == 13:
        stdout.write("\n")

Те числа, которые прерывают цикл, — это CTRL-C, CTRL-X и ESC соответственно. Число 13 — возврат каретки; в примере записывается перевод строки после каждого возврата каретки, чтобы избежать перезаписи текста.

Эквивалентом старого ASC(A$) в BASIC является ord(a) в Python. (А CHR$(A$) это chr(a).)

Обратите внимание, что это блокирует чтение. Если нажатие клавиши не ожидается, Python остановится на строке a = readchar(), пока не будет нажата клавиша. Чтобы получить полный эффект от BASIC INKEY$, вам нужно убедиться, что некоторые данные ожидают, прежде чем читать их. Вы можете сделать это с помощью библиотеки Python select.

from readchar import readchar
from sys import stdin, stdout
from select import select

def inkey():
    if select([stdin,],[],[],0.0)[0]:
        return readchar()
    return ''

a = ''
timer = 0
while a != 'Q':
    a = inkey()
    if a != '':
        stdout.write(a)
        stdout.flush()
        if ord(a) == 13:
            stdout.write("\n")
    timer += 1
    if timer > 1000000:
        print("Type faster, human!")
        timer = 0

Это определяет функцию inkey и возвращает пустую строку, если ничего не ждет. Если что-то читается, возвращается readchar(). Каждые 1 000 000 раз в цикле он говорит человеку на другом конце печатать быстрее.

В этой версии он заканчивается заглавной буквой «Q», так как это не блокирует CTRL-C, CTRL-X и ESC от выхода из программы.

Это может вызвать проблемы, если вы используете Windows, так как select.select по крайней мере одно время не работало в Windows. Однако у меня нет возможности проверить это.

Вы также можете посмотреть pynput, если вам не нужно, чтобы он выглядел точно так же, как BASIC. Каноническим способом сделать это в Python, вероятно, является установка события, которое вызывает функцию или метод. Ваш скрипт продолжает делать свое дело, и если эта функция (или метод) вызывается, он отменяет или изменяет действие основного цикла.

person Jerry Stratton    schedule 29.03.2020