#python #linux #python_3x
Как во время работы в терминале программы на python организовать обработку ввода с клавиатуры в фоновом режиме, не приостанавливая при этом работу самой программы? Например у нас есть цикл который должен каждую секунду печатать символ, а в случае если пользователь нажмет клавишу "стрелка вверх" вывести не слеующий символ, а предыдущий. (ОС Linux, python3.5) import time for x in ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'g', 'i', 'k', 'l']: print(x); time.sleep(1);
Ответы
Ответ 1
Для создания переносимых интерактивных консольных программ, можно prompt_toolkit модуль использовать. Чтобы печатать символы, меняя направление с помощью стрелок: #!/usr/bin/env python3 import asyncio import string from collections import deque from prompt_toolkit import prompt_async # $ pip install prompt_toolkit from prompt_toolkit.shortcuts import Keys, Registry BACKWARDS, STOP, FORWARD = 1, 0, -1 async def interactive_prompt(direction): registry = Registry() @registry.add_binding('q') @registry.add_binding(Keys.ControlC) def stop(event): direction[0] = STOP event.cli.set_return_value(False) # exit @registry.add_binding(Keys.Up) def backwards(event): direction[0] = BACKWARDS @registry.add_binding(Keys.Down) def forward(event): direction[0] = FORWARD await prompt_async('Press Up/Down/Ctrl-C/q> ', patch_stdout=True, # show prompt key_bindings_registry=registry) async def print_chars(direction, chars=deque(string.ascii_lowercase)): while direction[0]: print(chars[0]) await asyncio.sleep(1) chars.rotate(direction[0]) loop = asyncio.get_event_loop() direction = [FORWARD] loop.create_task(interactive_prompt(direction)) loop.run_until_complete(print_chars(direction))Ответ 2
Для сравнения, в качестве альтернативы asyncio версии, вариант с потоками: #!/usr/bin/env python import string import threading import time from collections import deque from prompt_toolkit import prompt # $ pip install prompt_toolkit from prompt_toolkit.shortcuts import Keys, Registry BACKWARDS, STOP, FORWARD = 1, 0, -1 def interactive_prompt(direction): registry = Registry() @registry.add_binding('q') @registry.add_binding(Keys.ControlC) def stop(event): direction[0] = STOP event.cli.set_return_value(False) # exit @registry.add_binding(Keys.Up) def backwards(event): direction[0] = BACKWARDS @registry.add_binding(Keys.Down) def forward(event): direction[0] = FORWARD prompt('Press Up/Down/Ctrl-C/q> ', patch_stdout=True, # show prompt key_bindings_registry=registry) def print_chars(direction, chars=deque(string.ascii_lowercase)): while direction[0]: print(chars[0]) time.sleep(1) chars.rotate(direction[0]) direction = [FORWARD] threading.Thread(target=print_chars, args=[direction], daemon=True).start() interactive_prompt(direction) Внешнее поведение совпадает c asyncio примером.
Комментариев нет:
Отправить комментарий