Python 3.6. нажатие клавиши -> упорядоченный выход во время выполнения программы - PullRequest
0 голосов
/ 02 мая 2020

Вопрос, который я часто задавал, но пока не нашел решения, подходящего для моей проблемы. Поэтому я был бы признателен за помощь в улучшении как моего кода, так и моего понимания Python.

. Я работаю над большим фрагментом кода, который имеет Grammatic Evolution и работает в нескольких вложенных (на данный момент неизбежных) классы.

Базовый класс (Geneti c) обрабатывает совокупность, каждый член совокупности является экземпляром класса Individual и оценивается с использованием класса Algorithm. Чтобы избежать чрезмерного усложнения - код, который выполняется в несколько слоев (с добавлением имитации Spice к миксу) и работает в течение ... довольно продолжительного времени - часов в некоторых случаях.

Это причина, почему я начал искать решение, которое позволило бы мне остановить выполнение таким образом, чтобы не все испортить. Если я использую обычную опцию ctrl + c, это просто уничтожает все и заставляет меня перезапустить ядро ​​и потерять все данные.

Я думаю о том, чтобы добавить в код своего рода монитор позволил бы мне ввести последовательность нажатия клавиш и затем сказать: «Хорошо, я вижу, что вы хотите завершить sh, я просто завершу текущую оценку l oop и выйду».

По моему убеждению, я не может использовать прерывание клавиатуры, так как это немедленно завершит выполнение кода. Скорее всего, мне понадобится флаг, который изменится, если будет обнаружен ключ ....

Любая помощь будет признательна.

Таким образом, чтобы подвести итог моей псевдоИдеи было бы так:

for each generation:
  if exit.flag != true:
    for each individual:
      evaluate individual
  else:
    write result
    finish and exit

when key detected set exit.flag to true

Спасибо!

Ответы [ 2 ]

0 голосов
/ 02 мая 2020

Нашел решение, используя pynput

from genetic.mainCore import Genetic
from grammar.basicDict import params
from algorithm.core import Algorithm
from pynput import keyboard


def on_activate_h():
    print('<ctrl>+<alt>+h pressed')
    global gen
    gen.forcEnd = True

listener = keyboard.GlobalHotKeys({'<ctrl>+<alt>+h': on_activate_h})
listener.start()

algi = Algorithm()
gen = Genetic(algi)
gen.initGrammar(params)
gen.initPopulation()
gen.run()

listener.stop()

Я изменил метод gen.run (), включив проверку forcEnd. Если установлено значение True, мы пропускаем оценку следующего поколения и завершаем работу. Протестировал и все работает, даже при использовании внешнего симулятора!

0 голосов
/ 02 мая 2020

Хотя можно обнаружить нажатие клавиши, вам не нужно это делать. Поскольку возможно «захватить» Ctrl- c!

try:
    code_execution()
except KeyboardInterrupt:
    print("Ctrl-c was pressed, ready to exit")

В основном тип исключения KeyboardInterrupt вызывается при нажатии Ctrl- c. И это то, что вы можете поймать и справиться любым способом, который считаете нужным. Вы можете прочитать больше об этом исключении, в частности здесь , и если вы новичок в обработке исключений, это является хорошей отправной точкой.

Бонусный балл - редкие исключения выполняются быстрее, чем операторы if.

Из ваших комментариев я понимаю, что вы не можете обернуть основное выполнение и предотвратить его остановку, поэтому я включаю другой метод. Перехват сигнала.
Ctrl- c отправляет процесс SIGINT, который мы можем настроить, на «перехват» и обработку его иначе, чем обычно (который завершается).

import signal, os
import time

FLAG = False


def handler(signum, frame):
    """
    This function will execute each time Ctrl-c is pressed or SIGINT
    is sent to the process (such as `kill <pid>`).
    """
    global FLAG
    print('Signal handler called with signal', signum)
    FLAG = True

# Setup so we process signal SIGINT (includes Ctrl-C) with handler
signal.signal(signal.SIGINT, handler)


while True and not FLAG:
    time.sleep(0.5)
    print("Working hard!")
else:
    print("Done!")

Вы можете прочитать немного больше о сигнале в Python в их документах . Это также стандартный метод межпроцессного взаимодействия, который вы можете использовать.

...