Reputation: 63
I have a main process (main.py) that is designed to run forever. It will only stop running when I close the console window. This is bundled as an .exe that I create using PyInstaller.
When I close the console window, I need it to run a function logout
, which sends an HTTP request to an AWS Lambda function.
How do I accomplish this?
Upvotes: 1
Views: 666
Reputation: 103
Here is an example of using ctypes, which is built into Python.
import time
import ctypes
from ctypes import wintypes
_HandlerRoutine = ctypes.WINFUNCTYPE(wintypes.BOOL, wintypes.DWORD)
CTRL_C_EVENT = 0
CTRL_BREAK_EVENT = 1
CTRL_CLOSE_EVENT = 2
CTRL_LOGOFF_EVENT = 5
CTRL_SHUTDOWN_EVENT = 6
def ctrl_handler(ctrl_type):
if ctrl_type in (CTRL_C_EVENT, CTRL_BREAK_EVENT, CTRL_CLOSE_EVENT, CTRL_SHUTDOWN_EVENT, CTRL_LOGOFF_EVENT):
print(f"Ctrl handler received {ctrl_type}.")
time.sleep(2)
return True
return False
_ctrl_handler = _HandlerRoutine(ctrl_handler)
kernel32 = ctypes.windll.kernel32
if not kernel32.SetConsoleCtrlHandler(_ctrl_handler, True):
raise ctypes.WinError(ctypes.get_last_error())
try:
print(f"process ready")
while True:
time.sleep(1)
except KeyboardInterrupt:
pass
It's also worth noting that if a program is not attached to a console, SetConsoleCtrlHandler has no effect. SetConsoleCtrlHandler should be called after a program is attached to a console or allocates a console.
If you want to run clean-up code when the program exits, try safe-exit
Upvotes: 1
Reputation: 63
To answer my own question for future users;
import win32con
import win32api
win32api.SetConsoleCtrlHandler(exit_handler, 1)
def logout():
# do something
def exit_handler(event):
if event in [win32con.CTRL_C_EVENT, win32con.CTRL_LOGOFF_EVENT,
win32con.CTRL_BREAK_EVENT, win32con.CTRL_SHUTDOWN_EVENT,
win32con.CTRL_CLOSE_EVENT]:
logout()
Where logout
is the function I want to run on console closure.
Be advised that you will want to only register the function once, as the same function can and will be registered more than once if you call SetConsoleCtrlHandler
multiple times.
It may also be a good practice to have a global flag of sorts, that will make sure the exit handler runs only once in the event of Windows sending multiple CTRL events.
If your logout
function takes more than 1-2 seconds to execute, the entire function may not run, as most console CTRL events are not ones that can be caught - they are solely alerts that Windows is about to end your process, and it is not possible to prevent closure.
Upvotes: 2