Search code examples
python-3.xevolutionary-algorithmpspice

Python 3.6. keypress -> orderly exit during program execution


A question I have seen posed often, but have not yet found a solution that fits my problem. I would therefore appreciate some help to improve both my code and my understanding of Python.

I'm working on a large chunk of code that features Grammatical Evolution and runs in several nested (unavoidable at the moment) classes.

The base class (Genetic) handles the population, each member of the population is an instance of Individual class and is evaluated using the Algorithm class. To avoid over-complicating - a code that runs in several layers (with Spice simulated added to the mix) and runs for... quite a long time - hours at some times.

This is the reason why I started to search for a solution that would allow me to stop the execution in a way that would not mess everything up. If I use the usual ctrl+c option it simply destroys everything and forces me to restart the kernel and loose all the data.

What I'm thinking about is adding a sort of a monitor to the code that would allow me to enter a keypress sequence and then say "Ok, I see you want to finish, I'll simply complete the current evaluation loop and exit".

In my belief I cannot use a keyboard interrupt since this would immediately exit the code execution. More likely I would need a flag that would change if the key is detected....

Any help would be appreciated.

So to summarize my pseudoIdea would be like this:

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

Thank you!


Solution

  • Found a solution using 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()
    

    I modified the gen.run() method to include a forcEnd check. If it is set to True we skip the evaluation of next generation and exit. Tested this and it works, even when using an external simulator!