Spyder IPython console Ctrl+C and Run‑command timeout: interaction and precedence
0 reputation · 19 Jan 2020, 20:44 UTC
0 reputation · 19 Jan 2020, 20:44 UTC
When executing a Python script via Spyder’s Run command, the IDE can enforce an execution timeout (Preferences → General → Advanced) and also respond to user‑initiated cancellation such as pressing Ctrl+C in the IPython console or clicking the Stop toolbar button. The goal is to clarify whether these two mechanisms operate independently, whether one takes precedence over the other, and what state the kernel or subprocess is left in when both are triggered.
Consider the constraints that timeout enforcement is only available in Spyder 5.0 and later, that signal delivery differs on Windows (CTRL_BREAK_EVENT), and that killing a subprocess may leave behind child processes spawned by the script. Under these conditions, it is unclear how Spyder resolves concurrent cancellation requests and whether any cleanup guarantees are provided.
What happens if a user presses Ctrl+C while a timeout is counting down? Does the Stop button override an active timeout, or does the timeout abort the Stop request? Does Spyder guarantee that no orphaned processes remain when both cancellation paths are invoked?
34775 reputation · 20 Jan 2020, 07:34 UTC
The three cancellation paths in Spyder — Ctrl+C in the IPython console, the Stop toolbar button, and the Run-command execution timeout (Spyder 5.0+) — are independent triggers racing toward the same target. There is no documented priority arbitration between them. Whichever fires first ends the execution; the later one becomes a no-op because there is no longer a running cell to act on. So if you press Ctrl+C while a timeout is counting down, the interrupt wins by timing alone, and the timeout timer — which is tied to that run — is simply discarded. The timeout does not "abort" your Stop request, and Stop does not wait for the timeout.
They differ in how they terminate, which determines the kernel's end state:
After Ctrl+C, the kernel survives but the namespace may be left in a partially executed state — variables assigned before the interrupt persist. After Stop or a timeout kill, the kernel is restarted and nothing survives. Critically, finally blocks and atexit handlers only get a chance to run on the KeyboardInterrupt path; a force-killed kernel runs no Python cleanup.
Spyder provides no general cleanup guarantee for processes your script spawned. If the script launched children via subprocess.Popen or multiprocessing, killing the kernel does not reliably reap grandchildren — they can be orphaned, and what survives depends on platform and spawn method (fork vs spawn). On Windows, signal delivery differs (CTRL_BREAK_EVENT / GenerateConsoleCtrlEvent rather than POSIX signals), making in-process interrupts to subprocesses less reliable, so forceful termination is more commonly the effective outcome there.
while True: pass with a short timeout configured; press Ctrl+C mid-run and confirm the interrupt fires before the timeout.subprocess.Popen(['sleep', '300']), trigger each cancellation path, and check the OS process list for survivors.One caveat: exact timeout semantics are version-dependent, so treat the above as the well-established 5.x/6.x behavior and verify against your installed release.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.