无法在 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 BaseException
而 KeyboardInterrupt
是 BaseException
的子类,所以你的 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
也可以 捕获一些您可能无法从中恢复的异常。例如 MemoryError
、SyntaxError
或 SystemError
通常表示出现了(真的)错误,这些不应该被吞下,因为这些 可能 不会是 "recoverable"(至少在大多数情况下)。
这意味着您应该观察您的代码在何种情况下可能抛出哪些异常,然后决定您可以从哪些异常中恢复。
你的情况:
input()
不应该失败,所以你不妨把它放在try
之外。
- 同样,您不希望比较失败,因此也可以将这些放在
try
块之外。因为如果 try
成功,您只希望该代码为 运行,所以您需要保护它,例如在 try
的 else
块中。
- 如果
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
块,您也可以 continue
在 except
块中:
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:
。唯一的例外是如果你真的想捕捉 SystemExit
、KeyboardInterrupt
或 GeneratorExit
并且知道如何适当地处理它们。 except Exception
你可能会侥幸逃脱,但对于任何你想经常使用的代码(或在生产代码中),你应该花时间找到更合适的例外。
我写这段代码是为了不断要求更多的输入,如果输入不是整数的话。但是,当我尝试在 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 BaseException
而 KeyboardInterrupt
是 BaseException
的子类,所以你的 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
也可以 捕获一些您可能无法从中恢复的异常。例如 MemoryError
、SyntaxError
或 SystemError
通常表示出现了(真的)错误,这些不应该被吞下,因为这些 可能 不会是 "recoverable"(至少在大多数情况下)。
这意味着您应该观察您的代码在何种情况下可能抛出哪些异常,然后决定您可以从哪些异常中恢复。
你的情况:
input()
不应该失败,所以你不妨把它放在try
之外。- 同样,您不希望比较失败,因此也可以将这些放在
try
块之外。因为如果try
成功,您只希望该代码为 运行,所以您需要保护它,例如在try
的else
块中。 - 如果
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
块,您也可以 continue
在 except
块中:
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:
。唯一的例外是如果你真的想捕捉SystemExit
、KeyboardInterrupt
或GeneratorExit
并且知道如何适当地处理它们。except Exception
你可能会侥幸逃脱,但对于任何你想经常使用的代码(或在生产代码中),你应该花时间找到更合适的例外。