无法在 Python 中中止 (ctrl+c)

Cannot abort (ctrl+c) in Python

我写这段代码是为了不断要求更多的输入,如果输入不是整数的话。但是,当我尝试在 python 交互式会话中中止它时,它一直要求输入。

为什么它会这样做,即使我按的是 Ctrl+C,这意味着中止。

def get_size(text):
    while True:
        try:
            i = int(input(text))
            if i >= 0 and i<24:
                break
        except:
            pass
    return i

a = get_size("Input: ")

Ctrl+C 表示 KeyboardInterrupt,但您的 except 块捕获并忽略它(以及所有其他异常)。即使是 Ctrl+D 也不会停止执行,所以我认为你应该终止进程。

您在 while 循环中创建了 try: except: 块。因此,每当脚本抛出错误时,except 只是通过并返回到 while 循环。

当您按下 Ctrl + C 时,Python 解释器捕获中断并抛出 KeyboardInterrupt 异常.因为你的 except 等同于 except BaseExceptionKeyboardInterruptBaseException 的子类,所以你的 except 会赶上 KeyboardInterrupt。您在 except 块中没有异常处理(如重新引发),因此程序将继续。

至少将 except 更改为 except Exception 因为异常是 BaseException 的子类但不子类 Exception (KeyboardInterrupt, SystemExit, 和 GeneratorExit) 并不是真的要被吞下。在极少数情况下,在重新饲养它们之前抓住它们并进行一些清理是有意义的。但几乎从来没有一个用例可以捕捉到它们而不再次提高它们。

可能用得上的Python documentation actually contains a hierarchy visualization of built-in exceptions

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StopAsyncIteration
      +-- ArithmeticError
      |    +-- FloatingPointError
      |    +-- OverflowError
      |    +-- ZeroDivisionError
      +-- AssertionError
      +-- AttributeError
      +-- BufferError
      +-- EOFError
      +-- ImportError
      |    +-- ModuleNotFoundError
      +-- LookupError
      |    +-- IndexError
      |    +-- KeyError
      +-- MemoryError
      ...

您可能会注意到 except Exception 也可以 捕获一些您可能无法从中恢复的异常。例如 MemoryErrorSyntaxErrorSystemError 通常表示出现了(真的)错误,这些不应该被吞下,因为这些 可能 不会是 "recoverable"(至少在大多数情况下)。

这意味着您应该观察您的代码在何种情况下可能抛出哪些异常,然后决定您可以从哪些异常中恢复。

你的情况:

  • input()不应该失败,所以你不妨把它放在try之外。
  • 同样,您不希望比较失败,因此也可以将这些放在 try 块之外。因为如果 try 成功,您只希望该代码为 运行,所以您需要保护它,例如在 tryelse 块中。
  • 如果 TypeError 是不受支持的类型,int() 可能会失败,但是 input 总是 returns 字符串。 String 是 int() 可接受的类型,因此人们不会期望会发生这种情况。
  • 所以您在这里可能遇到的唯一 "expected" 异常是 ValueError。如果字符串不能解释为整数,则抛出。

所以我会使用:

def get_size(text):
    while True:
        input_text = input(text)
        try:
            i = int(input_text)
        except ValueError:
            pass
        else:
            if 0 <= i < 24:
                return i

或者如果您不想要 else 块,您也可以 continueexcept 块中:

def get_size(text):
    while True:
        input_text = input(text)
        try:
            i = int(input_text)
        except ValueError:
            continue
        if 0 <= i < 24:
            return i

您使用哪一个主要是个人喜好问题。两者应该工作相同。

总结一下:

  • 确定允许(从您的角度)失败的最小代码量,不要在 try 块中放置任何其他内容。
  • 确保只捕获 "recoverable" 异常。在大多数情况下,异常类型就足够了。但有时 检查异常消息以确保它确实是您要捕获的异常可能是有意义的。
  • 切勿使用 except:except BaseException:。唯一的例外是如果你真的想捕捉 SystemExitKeyboardInterruptGeneratorExit 并且知道如何适当地处理它们。 except Exception 你可能会侥幸逃脱,但对于任何你想经常使用的代码(或在生产代码中),你应该花时间找到更合适的例外。