Skip to content

Instantly share code, notes, and snippets.

@ynkdir
Created June 23, 2026 14:32
Show Gist options
  • Select an option

  • Save ynkdir/5551f00666741aadef7c63a28ad3c65b to your computer and use it in GitHub Desktop.

Select an option

Save ynkdir/5551f00666741aadef7c63a28ad3c65b to your computer and use it in GitHub Desktop.
Cancel input() with CancelIoEx()
# Cancel input() with CancelIoEx().
#
# There is known problem: https://github.com/microsoft/terminal/issues/12143
import msvcrt
import sys
import threading
from win32more import UInt32
from win32more.Windows.Win32.Foundation import TRUE
from win32more.Windows.Win32.System.Console import INPUT_RECORD, KEY_EVENT, WriteConsoleInput
from win32more.Windows.Win32.System.IO import CancelIoEx
from win32more.Windows.Win32.UI.Input.KeyboardAndMouse import VK_RETURN
exiting = threading.Event()
console_input = msvcrt.get_osfhandle(sys.stdin.fileno())
def worker():
while not exiting.wait(3):
cancel_console_input_blocking()
def cancel_console_input_blocking():
# Cancel input() in main thread.
CancelIoEx(console_input, None)
# WORKAROUND: Reset console internal state by sending key event.
# You need to press Enter twice for second input() without this.
rec = INPUT_RECORD()
rec.EventType = KEY_EVENT
rec.Event.KeyEvent.bKeyDown = TRUE
rec.Event.KeyEvent.wRepeatCount = 1
rec.Event.KeyEvent.wVirtualKeyCode = VK_RETURN
rec.Event.KeyEvent.uChar.UnicodeChar = "\r"
rec.Event.KeyEvent.dwControlKeyState = 0
WriteConsoleInput(console_input, rec, 1, UInt32(0))
def main():
t = threading.Thread(target=worker)
t.start()
while True:
try:
result = input("Press Enter to exit (canceled in 3 seconds)")
print(f"{result=}")
break
except EOFError:
print("Canceled!")
except KeyboardInterrupt:
print("Interrupted!")
break
exiting.set()
t.join()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment