Python 3.6。按键 -> 程序执行期间有序退出
Python 3.6. keypress -> orderly exit during program execution
一个我经常看到的问题,但还没有找到适合我问题的解决方案。
因此,如果能帮助我改进我的代码和我对 Python.
的理解,我将不胜感激
我正在处理一大块代码,这些代码具有语法演变的特点,并在多个嵌套(目前不可避免)中运行 classes.
基础class(遗传)处理种群,种群的每个成员都是个体class的一个实例,并使用算法class进行评估。为了避免过于复杂 - 代码在多个层中运行(将 Spice 模拟添加到混合中)并运行......相当长的时间 - 有时数小时。
这就是我开始寻找一种解决方案的原因,该解决方案可以让我以一种不会弄乱一切的方式停止执行。如果我使用通常的 ctrl+c 选项,它只会破坏所有内容并迫使我重新启动内核并丢失所有数据。
我正在考虑的是在代码中添加一种监视器,允许我输入按键序列,然后说 "Ok, I see you want to finish, I'll simply complete the current evaluation loop and exit"。
我认为我不能使用键盘中断,因为这会立即退出代码执行。如果检测到密钥,我更有可能需要一个会改变的标志....
如有任何帮助,我们将不胜感激。
所以总结一下我的伪想法是这样的:
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
谢谢!
虽然可以检测到按键,但您不必这样做。因为可以 "capture" a Ctrl-c!
try:
code_execution()
except KeyboardInterrupt:
print("Ctrl-c was pressed, ready to exit")
基本上,当按下 Ctrl-c 时会引发异常类型 KeyboardInterrupt
。这是你可以用任何你认为合适的方式捕捉和处理的东西。您可以阅读更多关于此异常的信息,特别是 here and in case you're new to exception handling, this 是一个很好的起点。
奖励点 - 罕见的异常比 if 语句更快。
根据您的评论,我了解到您无法包装主执行并阻止其停止,因此我包含了另一种方法。信号捕获。
Ctrl-c 将我们可以配置的进程 SIGINT 发送到 "trap" 并以不同于正常(正在退出)的方式处理它。
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!")
您可以在他们的 docs 中的 Python 中阅读更多关于信号的信息。它也是进程间通信的标准方法,您可以利用它。
找到使用 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,我们将跳过下一代的评估并退出。对此进行了测试,即使使用外部模拟器也能正常工作!
一个我经常看到的问题,但还没有找到适合我问题的解决方案。 因此,如果能帮助我改进我的代码和我对 Python.
的理解,我将不胜感激我正在处理一大块代码,这些代码具有语法演变的特点,并在多个嵌套(目前不可避免)中运行 classes.
基础class(遗传)处理种群,种群的每个成员都是个体class的一个实例,并使用算法class进行评估。为了避免过于复杂 - 代码在多个层中运行(将 Spice 模拟添加到混合中)并运行......相当长的时间 - 有时数小时。
这就是我开始寻找一种解决方案的原因,该解决方案可以让我以一种不会弄乱一切的方式停止执行。如果我使用通常的 ctrl+c 选项,它只会破坏所有内容并迫使我重新启动内核并丢失所有数据。
我正在考虑的是在代码中添加一种监视器,允许我输入按键序列,然后说 "Ok, I see you want to finish, I'll simply complete the current evaluation loop and exit"。
我认为我不能使用键盘中断,因为这会立即退出代码执行。如果检测到密钥,我更有可能需要一个会改变的标志....
如有任何帮助,我们将不胜感激。
所以总结一下我的伪想法是这样的:
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
谢谢!
虽然可以检测到按键,但您不必这样做。因为可以 "capture" a Ctrl-c!
try:
code_execution()
except KeyboardInterrupt:
print("Ctrl-c was pressed, ready to exit")
基本上,当按下 Ctrl-c 时会引发异常类型 KeyboardInterrupt
。这是你可以用任何你认为合适的方式捕捉和处理的东西。您可以阅读更多关于此异常的信息,特别是 here and in case you're new to exception handling, this 是一个很好的起点。
奖励点 - 罕见的异常比 if 语句更快。
根据您的评论,我了解到您无法包装主执行并阻止其停止,因此我包含了另一种方法。信号捕获。
Ctrl-c 将我们可以配置的进程 SIGINT 发送到 "trap" 并以不同于正常(正在退出)的方式处理它。
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!")
您可以在他们的 docs 中的 Python 中阅读更多关于信号的信息。它也是进程间通信的标准方法,您可以利用它。
找到使用 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,我们将跳过下一代的评估并退出。对此进行了测试,即使使用外部模拟器也能正常工作!