Зависит от того, что ты понимаешь под досрочным завершением, и что ты хочешь сделать в рамках реакции на это завершение.
Например, os._exit() прибьёт процесс так, что никакое завершение не отработает. Аналогично, есть другеи ситуации, когда процесс прибивается "снаружи". В таких случаях только мониторинг со стороны родительского процесса, только хардкор.
В простейшем случае можно завернуть тело программы в try-except, try-finally или кастомный блок with (скажем, через contextlib.contextmanager).
Также можно посмотреть в сторону модуля atexit, но там свобода действий будет более ограничена.