Python 空闲和键盘中断

发布于 2024-11-18 21:25:51 字数 211 浏览 6 评论 0 原文

空闲状态下的键盘中断在 90% 的情况下对我有效,但我想知道为什么它们并不总是有效。在空闲状态下,如果我这样做

import time
time.sleep(10)

,然后使用 Ctrl+C 尝试键盘中断,它不会中断该进程,直到休眠 10 秒后。

相同的代码和通过 Ctrl+C 实现的键盘中断可立即在 shell 中运行。

KeyboardInterrupts in Idle work for me 90% of the time, but I was wondering why they don't always work. In Idle, if I do

import time
time.sleep(10)

and then attempt a KeyboardInterrupt using Ctrl+C, it does not interrupt the process until after sleeping for 10 seconds.

The same code and a KeyboardInterrupt via Ctrl+C works immediately in the shell.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

来世叙缘 2024-11-25 21:25:52

快速浏览一下 IDLE 源代码就会发现,KeyboardInterrupts 有一些特殊情况处理: http://svn.python.org/view/python/tags/r267/Lib/idlelib/PyShell.py?annotate=88851

最重要的是,代码实际上是在主 IDLE gui 进程通过 RPC 与之通信的独立进程。在该模型下您将得到不同的行为 - 最好只使用规范解释器进行测试(通过命令行、交互式等)

============

深入挖掘...

套接字RPC 服务器上的辅助线程在辅助线程中进行管理,该线程应该使用对 thread.interrupt_main() 的调用来传播 KeyboardInterrupt ( http://svn.python.org/view /python/tags/r267/Lib/idlelib/run.py?annotate=88851 )。那里的行为并不符合预期...这篇文章暗示,由于某种原因,interrupt_main 没有提供您期望的粒度级别: http://bytes.com/topic/python/answers/38386-thread-interrupt_main-doesnt-seem-work

cPython 中的异步 API 函数有点愚蠢(根据我的经验)解释器循环的处理方式,所以这并不令我感到惊讶。 Interrupt_main() 调用 PyErr_SetInterrupt() 异步通知解释器处理主线程中的 SIGINT。来自 http://docs.python.org/c-api/exceptions.html# PyErr_SetInterrupt

该函数模拟的效果
SIGINT 信号到达 - 下一个
调用 PyErr_CheckSignals() 的时间,
将引发键盘中断

这将要求解释器在再次调用 PyErr_CheckSignals() 之前执行任意数量的字节码指令 - 这在 time.sleep() 期间可能不会发生。我敢说这是模拟 SIGINT 而不是实际发出 SIGINT 信号的缺陷。

A quick glance at the IDLE source reveals that KeyboardInterrupts have some special case handling: http://svn.python.org/view/python/tags/r267/Lib/idlelib/PyShell.py?annotate=88851

On top of that, code is actually executed in a separate process which the main IDLE gui process communicates with via RPC. You're going to get different behavior under that model - it's best to just test with the canonical interpreter (via command line, interactive, etc.)

============

Digging deeper...

The socket on the RPC server is managed in a secondary thread which is supposed to propagate a KeyboardInterrupt using a call to thread.interrupt_main() ( http://svn.python.org/view/python/tags/r267/Lib/idlelib/run.py?annotate=88851 ). Behavior is not as expected there... This posting hints that for some reason, interrupt_main doesn't provide the level of granularity that you would expect: http://bytes.com/topic/python/answers/38386-thread-interrupt_main-doesnt-seem-work

Async API functions in cPython are a little goofy (from my experience) due to how the interpreter loop is handled, so it doesn't surprise me. interrupt_main() calls PyErr_SetInterrupt() to asynchronously notify the interpreter to handle a SIGINT in the main thread. From http://docs.python.org/c-api/exceptions.html#PyErr_SetInterrupt:

This function simulates the effect of
a SIGINT signal arriving — the next
time PyErr_CheckSignals() is called,
KeyboardInterrupt will be raised

That would require the interpreter to go though whatever number of bytecode instructions before PyErr_CheckSignals() is called again - something that probably doesn't happen during a time.sleep(). I would venture to say that's a wart of simulating a SIGINT rather than actually signaling a SIGINT.

高冷爸爸 2024-11-25 21:25:52

请参阅这篇文章

我引用:

如果您尝试停止 CPython 程序
使用 Control-C,解释器
抛出键盘中断异常。

这是有道理的,因为线程休眠了 10 秒,因此在 10 秒过去之前不能抛出异常。但是,ctrl + c 始终在 shell 中工作,因为您试图停止进程,而不是抛出 python KeyboardInterrupt 异常。

另请参阅之前回答的问题

我希望这有帮助!

See This article:

I quote:

If you try to stop a CPython program
using Control-C, the interpreter
throws a KeyboardInterrupt exception.

It makes some sense, because the thread is asleep for 10 seconds and so exceptions cannot be thrown until the 10 seconds pass. However, ctrl + c always work in the shell because you are trying to stop a process, not throw a python KeyboardInterrupt exception.

Also, see this previously answered question.

I hope this helps!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文