Python 3.6.keypress ->在程序执行过程中有序退出。

问题描述 投票:0回答:1

一个我经常看到的问题,但还没有找到适合我的问题的解决方案。因此,我希望得到一些帮助,以改善我的代码和我对 Python 的理解。

我正在处理一大块代码,它的特点是语法进化,并在几个嵌套的 (目前不可避免的) 类中运行。

基类(Genetic)处理种群,种群中的每个成员都是 Individual 类的实例,并使用 Algorithm 类进行评估。为了避免过度复杂化--一个代码要运行好几层(加上Spice模拟),而且运行时间......相当长--有些时候要几个小时。

这就是为什么我开始寻找一种解决方案,让我能够以一种不会搞砸一切的方式停止执行。如果我使用通常的ctrl+c选项,它会简单地摧毁一切,迫使我重新启动内核,并丢失所有的数据。

我想的是在代码中添加一种监视器,让我输入一个按键序列,然后说:"好的,我知道你想结束,我将简单地完成当前的评估循环并退出"。

在我看来,我不能使用键盘中断,因为这将立即退出代码执行。更有可能的是,我需要一个标志,如果检测到按键就会改变......。

如果有任何帮助,我将感激不尽。

所以,总结一下我的伪想法是这样的。

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

谢谢你!

python-3.x evolutionary-algorithm pspice
1个回答
0
投票

使用 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
投票

虽然有可能检测到一个按键,但你不必这样做。因为可以 "捕获 "一个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中阅读更多关于信号的内容,在他们的 文件. 这也是一种标准的进程间通信方法,你可以利用它。

© www.soinside.com 2019 - 2024. All rights reserved.