Python:捕获Ctrl-C命令.提示“真的要退出(y/n)",如果没有,请恢复执行 [英] Python: Catch Ctrl-C command. Prompt "really want to quit (y/n)", resume execution if no

查看:425
本文介绍了Python:捕获Ctrl-C命令.提示“真的要退出(y/n)",如果没有,请恢复执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个程序可能需要很长时间才能执行.在主模块中,我有以下内容:

I have a program that may have a lengthy execution. In the main module I have the following:

import signal
def run_program()
   ...time consuming execution...

def Exit_gracefully(signal, frame):
    ... log exiting information ...
    ... close any open files ...
    sys.exit(0)

if __name__ == '__main__':
    signal.signal(signal.SIGINT, Exit_gracefully)
    run_program()

这很好用,但是我希望有可能在捕获SIGINT时暂停执行,提示用户是否真的要退出,并在他们决定不希望的情况下恢复我在run_program()中离开的位置退出.

This works fine, but I'd like the possibility to pause execution upon catching SIGINT, prompting the user if they would really like to quit, and resuming where I left off in run_program() if they decide they don't want to quit.

我能想到的唯一方法是在一个单独的线程中运行该程序,让主线程在其上等待并准备捕获SIGINT.如果用户想要退出主线程,则可以进行清理并杀死子线程.

The only way I can think of doing this is running the program in a separate thread, keeping the main thread waiting on it and ready to catch SIGINT. If the user wants to quit the main thread can do cleanup and kill the child thread.

有没有更简单的方法?

推荐答案

python信号处理程序似乎不是真正的信号处理程序;它不是真正的信号处理程序.那就是它们在事实之后,在正常流程中以及在C处理程序已经返回之后发生.因此,您将尝试将退出逻辑放入信号处理程序中.由于信号处理程序在主线程中运行,因此也会在该线程中阻止执行.

The python signal handlers do not seem to be real signal handlers; that is they happen after the fact, in the normal flow and after the C handler has already returned. Thus you'd try to put your quit logic within the signal handler. As the signal handler runs in the main thread, it will block execution there too.

类似的事情似乎很好用.

Something like this seems to work nicely.

import signal
import time
import sys

def run_program():
    while True:
        time.sleep(1)
        print("a")

def exit_gracefully(signum, frame):
    # restore the original signal handler as otherwise evil things will happen
    # in raw_input when CTRL+C is pressed, and our signal handler is not re-entrant
    signal.signal(signal.SIGINT, original_sigint)

    try:
        if raw_input("\nReally quit? (y/n)> ").lower().startswith('y'):
            sys.exit(1)

    except KeyboardInterrupt:
        print("Ok ok, quitting")
        sys.exit(1)

    # restore the exit gracefully handler here    
    signal.signal(signal.SIGINT, exit_gracefully)

if __name__ == '__main__':
    # store the original SIGINT handler
    original_sigint = signal.getsignal(signal.SIGINT)
    signal.signal(signal.SIGINT, exit_gracefully)
    run_program()

代码在raw_input的持续时间内恢复原始信号处理程序; raw_input本身不可重新输入,然后重新输入 会导致RuntimeError: can't re-enter readlinetime.sleep升高,这是我们不希望的,因为它比KeyboardInterrupt难捕获.相反,我们让两个连续的Ctrl-C引发KeyboardInterrupt.

The code restores the original signal handler for the duration of raw_input; raw_input itself is not re-entrable, and re-entering it will lead to RuntimeError: can't re-enter readline being raised from time.sleep which is something we don't want as it is harder to catch than KeyboardInterrupt. Rather, we let 2 consecutive Ctrl-C's to raise KeyboardInterrupt.

这篇关于Python:捕获Ctrl-C命令.提示“真的要退出(y/n)",如果没有,请恢复执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆