Как использовать клавишу «esc», чтобы завершить программу в любой момент/вернуться в предыдущее меню?

В настоящее время у меня есть программа, которая открывается с меню, пользователь может выбрать параметр и перейти к этой функции. Однако, если в какой-либо момент нажать клавишу Esc, она должна вернуться в предыдущее меню или полностью выйти из программы, если она находится на вершине иерархии.

До сих пор у меня это работало, если пользователь нажимает Esc, затем нажимает Enter, он выходит/или возвращается в предыдущее меню. Но я хотел бы сделать так, чтобы пользователю не приходилось нажимать только клавишу Esc. Я пытался использовать многопроцессорную библиотеку для создания процесса для основного кода, но это останавливает работу функции input() для всего пользовательского ввода, который требуется моей программе.

def my_code():
    while True:
        print("a. do something\n")
        print("b. do something\n")
        print("c. do something\n")
        print("d. do something\n")
        print("e. do something\n")
        print("f. do something\n")
        print("g. do something\n")
        choice = input("Please pick an option (a-g):")

        if choice == 'a' or choice == 'A':
            function_a()

if __name__ == '__main__':
    p = multiprocessing.Process(target = my_code)
    p.start()

    if getch.getch() == '\x1b':
        os.kill(p.pid, signal.SIGINT)

На самом деле, если в какой-то момент нажать Esc, если он находится в этом меню, то программа должна выйти. Но когда я запускаю это, я получаю сообщение об ошибке

choice = input("Please pick an option (a-g):")
EOFError: EOF when reading a line

Есть ли лучший способ реализовать это вместо создания потока multiprocessing?


person shady mccoy    schedule 16.06.2019    source источник


Ответы (1)


Используйте библиотеку клавиатуры для ожидания клавиш

pip install keyboard

Вы можете использовать поток в режиме демона для ввода значений

def function_a():
   print("call function_a")

def my_code():
    while True:
        print("a. do something\n")
        print("b. do something\n")
        print("c. do something\n")
        print("d. do something\n")
        print("e. do something\n")
        print("f. do something\n")
        print("g. do something\n")
        choice = input("Please pick an option (a-g):")

        if choice == 'a' or choice == 'A':
            function_a()

threading.Thread(target = my_code, daemon=True).start()

Ваш основной поток будет ждать, пока не будет нажата клавиша Esc, а затем завершит работу, убив как ваш основной поток, так и поток демона.

keyboard.wait("esc")
sys.exit()

Полный пример:

import keyboard
import threading
import sys

def function_a():
   print("call function_a")

def my_code():
    while True:
        print("a. do something\n")
        print("b. do something\n")
        print("c. do something\n")
        print("d. do something\n")
        print("e. do something\n")
        print("f. do something\n")
        print("g. do something\n")
        choice = input("Please pick an option (a-g):")

        if choice == 'a' or choice == 'A':
            function_a()

my_thread = threading.Thread(target = my_code, daemon=True).start()
keyboard.wait("esc")
sys.exit()
person Mariano Ezequiel Andres    schedule 17.06.2019
comment
Будет ли работать что-то подобное этому, если нажать «esc» в функции function_a и вернуться к my_code? - person shady mccoy; 17.06.2019
comment
Извините, я не понимаю, о чем вы спрашиваете. Но пока вы выполняете команду keyboard.wait(esc), программа будет ждать, пока не будет нажата клавиша 'esc'. - person Mariano Ezequiel Andres; 17.06.2019
comment
Извините, позвольте мне уточнить, так что в принципе можно сделать это таким образом. Если 'esc' нажата в любой функции, кроме my_code, она возвращается к my_code, а если она находится в my_code, происходит выход. - person shady mccoy; 17.06.2019
comment
О, хорошо, я понял. Это намного сложнее, так как с этим решением вы ожидаете глобального нажатия клавиши «esc». Для того, чтобы делать то, что вы хотите, может потребоваться несколько потоков или система событий или какой-то более умный способ реализовать несколько вложенных подменю. Я постараюсь что-нибудь придумать и дам вам знать, если у меня получится - person Mariano Ezequiel Andres; 17.06.2019