为什么我无法在 python 中处理键盘中断?

2024-03-03

我正在 Windows 上编写 python 2.6.6 代码,如下所示:

try:
    dostuff()
except KeyboardInterrupt:
    print "Interrupted!"
except:
    print "Some other exception?"
finally:
    print "cleaning up...."
    print "done."

dostuff()是一个永远循环的函数,一次从输入流中读取一行并对其进行操作。我希望能够在按下 ctrl-c 时停止它并进行清理。

相反发生的事情是下面的代码except KeyboardInterrupt:根本没有运行。唯一打印的是“清理...”,然后打印回溯,如下所示:

Traceback (most recent call last):
  File "filename.py", line 119, in <module>
    print 'cleaning up...'
KeyboardInterrupt

因此,异常处理代码没有运行,并且回溯声称发生了键盘中断在finally子句中,这是没有意义的,因为按下 ctrl-c 是导致该部分首先运行的原因!即使是通用的except:子句未运行。

EDIT:根据评论,我替换了内容try:使用 sys.stdin.read() 阻止。问题仍然完全按照描述发生,第一行finally:阻止运行然后打印相同的回溯。

EDIT #2:如果我在读取后添加几乎任何内容,处理程序就会起作用。所以,这失败了:

try:
    sys.stdin.read()
except KeyboardInterrupt:
    ...

但这有效:

try:
    sys.stdin.read()
    print "Done reading."
except KeyboardInterrupt:
    ...

这是打印的内容:

Done reading. Interrupted!
cleaning up...
done.

因此,出于某种原因,“阅读完毕”。即使异常发生在上一行,也会打印该行。这并不是真正的问题 - 显然我必须能够处理“try”块内任何地方的异常。但是,打印无法正常工作 - 它不会像预期的那样打印换行符! “Interruped”打印在同一行...前面有一个空格,出于某种原因...?不管怎样,之后代码就完成了它应该做的事情。

在我看来,这是在阻塞系统调用期间处理中断的一个错误。


遗憾的是,异步异常处理并不可靠(信号处理程序引发的异常、通过 C API 的外部上下文等)。如果代码中对哪一段代码负责捕获异步异常进行了一些协调(除了非常关键的函数之外,调用堆栈中的最高可能值似乎是合适的),那么您可以增加正确处理异步异常的机会。

被调用的函数(dostuff)或堆栈下方的函数本身可能会捕获您没有/无法解释的 KeyboardInterrupt 或 BaseException 。

这个简单的案例在 python 2.6.6 (x64) Interactive + Windows 7 (64bit) 上运行得很好:

>>> import time
>>> def foo():
...     try:
...             time.sleep(100)
...     except KeyboardInterrupt:
...             print "INTERRUPTED!"
...
>>> foo()
INTERRUPTED!  #after pressing ctrl+c

EDIT:

经过进一步调查,我尝试了我认为其他人用来重现该问题的示例。我太懒了所以省略了“终于”

>>> def foo():
...     try:
...             sys.stdin.read()
...     except KeyboardInterrupt:
...             print "BLAH"
...
>>> foo()

按 CTRL+C 后立即返回。当我立即尝试再次调用 foo 时,有趣的事情发生了:

>>> foo()

Traceback (most recent call last):
  File "c:\Python26\lib\encodings\cp437.py", line 14, in decode
    def decode(self,input,errors='strict'):
KeyboardInterrupt

我没有按 CTRL+C 就立即引发了异常。

这似乎是有道理的——看来我们正在处理 Python 中如何处理异步异常的细微差别。在实际弹出异步异常然后在当前执行上下文中引发之前,可​​能需要几个字节码指令。 (这是我过去玩它时看到的行为)

请参阅 C API:http://docs.python.org/c-api/init.html#PyThreadState_SetAsyncExc http://docs.python.org/c-api/init.html#PyThreadState_SetAsyncExc

因此,这在一定程度上解释了为什么在此示例中执行finally语句的上下文中引发KeyboardInterrupt:

>>> def foo():
...     try:
...             sys.stdin.read()
...     except KeyboardInterrupt:
...             print "interrupt"
...     finally:
...             print "FINALLY"
...
>>> foo()
FINALLY
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in foo
KeyboardInterrupt

自定义信号处理程序与解释器的标准键盘中断/CTRL+C 处理程序的疯狂混合可能会导致这种行为。例如, read() 调用看到信号并进行保释,但它在取消注册其处理程序后重新引发信号。如果不检查解释器代码库,我就无法确定。

这就是为什么我通常回避使用异步异常......

EDIT 2

我认为错误报告是一个很好的案例。

再次更多理论...(仅基于阅读代码)请参阅文件对象源:

file_read 调用 Py_UniversalNewlineFread()。 fread 可以返回错误,errno = EINTR(它执行自己的信号处理)。在这种情况下,Py_UniversalNewlineFread() 会终止,但不会使用 PyErr_CheckSignals() 执行任何信号检查,以便可以同步调用处理程序。 file_read 清除文件错误,但也不调用 PyErr_CheckSignals()。

有关如何使用它的示例,请参阅 getline() 和 getline_via_fgets()。该模式记录在针对类似问题的错误报告中:(http://bugs.python.org/issue1195 http://bugs.python.org/issue1195)。因此,信号似乎是由解释器在不确定的时间处理的。

我想深入研究没有什么价值,因为仍然不清楚 sys.stdin.read() 示例是否是“dostuff()”函数的正确模拟。 (可能存在多个错误)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么我无法在 python 中处理键盘中断? 的相关文章

随机推荐

  • 如何删除使用 django-ckeditor 上传的图像?

    我已经在 Django 管理界面的 CKEditor 中上传了一些图像 我可以通过单击编辑器中的 图像 按钮来浏览和选择图像 然后在弹出的窗口中单击 浏览服务器 这是弹出窗口的屏幕截图 我的问题是 如何删除服务器上的图像 不幸的是这是真的
  • “Enter-PSSession -Session”,阻止调用进程,直到用户键入“exit”

    我在将 New PSSession 与 Enter PSSession session 结合使用时遇到问题 也就是说 在用户在交互式 PSSession 中键入 exit 之前 无法阻止调用进程 这是一个代码示例 s New PSSessi
  • React-router 不会在不同路径上重新挂载组件

    我的反应应用程序中有一个组件 它是一个表单 该表格用于创建新许可证或编辑现有许可证 无论哪种方式 它都只是一个组件 它会检查 componentDidMount 是哪个 pageType 添加 更新 现在我的问题是 当我使用表单编辑许可证
  • 在 C# 中枚举 Collection 的子集?

    在 C 中是否有一种好方法可以仅枚举 Collection 的子集 也就是说 我有大量对象的集合 例如 1000 个 但我只想枚举元素 250 340 有没有一种好方法可以获取集合子集的枚举器 而无需使用另一个集合 编辑 应该提到这是使用
  • 如何从 Java 7 调用 Kotlin 挂起协程函数

    我正在尝试从 Java 7 调用 Kotlin 函数 我正在使用协程 并且这个被调用的函数正在挂起 例如 suspend fun suspendingFunction Boolean return async longRunningFunc
  • Scala 元组列表到平面列表

    我有元组对列表 List String String 并想将其展平为字符串列表 List String 一些选项可能是 连接 list map t gt t 1 t 2 一个接一个交错 在您发表评论后 您似乎在要求这个 list flatM
  • 计算一系列值的 RGB 值以创建热图

    我正在尝试用 python 创建热图 为此 我必须为可能值范围内的每个值分配一个 RGB 值 我想将颜色从蓝色 最小值 更改为绿色到红色 最大值 下面的图片示例解释了我对颜色组合的看法 我们的范围是从 1 纯蓝色 到 3 纯红色 2 介于两
  • Angular2的ng-select如何实现分组?

    我正在实现多个选择下拉菜单Angular2项目按照这个link https plnkr co edit JcG8uO9nIfSGMEKdLf0Y p preview 但现在我必须在这个多选下拉列表中显示分组 那么我该如何实现呢 或者有其他插
  • Javafx 橡皮筋调整大小错误

    所以 我的橡皮筋课上有一个错误 但我似乎无法修复它 我基本上做的是 我有一个边框窗格 它是我想要调整大小的节点的外部窗格 我为这个 borderpane 指定一个宽度为 1 像素的边框 查看 css 我还为这个边框面板分配了 4 个矩形 每
  • Angular 2 - 锚链接到当前页面上的元素[重复]

    这个问题在这里已经有答案了 如果问题标题不清楚 我有一个带有某些 链接 部分的网页 因此有人可以单击该链接并转到同一模板上的元素 这并不一定意味着更改 URL 我尝试过的要点 a href Section B a a href p Cont
  • 升级到 macOS Sierra 后无法从终端运行 R

    我最近将 MacBook 更新到了 macOS Sierra 版本 10 12 3 16D32 并且我无法再直接从终端运行 R DN51ssqi kjytay R bash R command not found DN51ssqi kjyt
  • ACM 交互器冻结

    我正在尝试使用 Swing 和 ACM 交互器制作一个非常简单的程序 它直接取自课堂讲义 但在我的计算机上不起作用 当我运行它时 它可以正常运行大约半秒 然后短暂闪烁 重新加载 然后所有按钮和文本字段功能都丢失 这是代码 import ac
  • ECONNREFUSED 用于从本地主机到另一个本地主机的代理请求

    首先 我是角度新手 我正在遵循教程视频 https youtu be 2OHbjep WjQ一步步 我在这个问题上被困了近两周 并花了很多时间在其他类似的论坛上寻找解决方案 我意识到这是一个常见的错误 但在尝试了几十个左右的解决方案但没有成
  • 如何捕获整数(0)?

    假设我们有一个语句可以生成integer 0 e g a lt which 1 3 5 捕捉这个最安全的方法是什么 这是 R 打印零长度向量 整数一 的方式 因此您可以测试a长度为 0 R gt length a 1 0 可能值得重新考虑您
  • python 中的图谱聚类

    我想使用谱聚类在 python 中对图进行聚类 谱聚类是一种更通用的技术 不仅可以应用于图形 还可以应用于图像或任何类型的数据 但是 它被认为是一种特殊的技术graph聚类技术 遗憾的是 我无法在线找到 python 中的谱聚类图的示例 S
  • 使用 CSS 制作进度条动画

    所以 我在这个页面上有几个不同的进度条 http kaye at play goals http kaye at play goals 这是我的 HTML 和 CSS div class meter span style width 100
  • jQuery $(window).load(); 是否执行事件不会在没有 声明的页面上触发? (...在 Chrome 扩展内容脚本中)

    我正在开发一个可以操作网页的 Google Chrome 扩展 但在它部分加载 DOM 或完全加载 带有图像 之后 看来现在很多网站都使用 声明 或者它的一些变体 但许多其他人没有 问题主要是关于 HTML 文档类型 我不确定其他的 是否可
  • 在 VBA 中执行存储过程的两种方法,哪一种更好?

    背景 使用前端 Ms Access 2010 和后端 SQL Server 2008 Management Studio 为了执行存储过程 我一直使用一个相当漫长的过程 如下所示 in VBA Set Conn New ADODB conn
  • 如何使用 NSPredicate 过滤包含其他类的复合对象的 NSMutableSet?

    新手问题 我有 3 个类 其中 3 个是 NSOBject 的子类 收藏类 有 2 个属性 masterSong 作为 NSMutableSet 强 非原子 和listOfPlaylists 作为 NSMutableArray 强 非原子
  • 为什么我无法在 python 中处理键盘中断?

    我正在 Windows 上编写 python 2 6 6 代码 如下所示 try dostuff except KeyboardInterrupt print Interrupted except print Some other exce