def test_on_exception_hook(tmp_path):
    """Test the on_exception callback hook and the trainer interrupted flag."""
    model = BoringModel()

    class InterruptCallback(Callback):
        def __init__(self):
            super().__init__()

        def on_train_batch_start(self, trainer, pl_module, batch, batch_idx):
            raise KeyboardInterrupt

        def on_test_start(self, trainer, pl_module):
            raise MisconfigurationException

    class HandleInterruptCallback(Callback):
        def __init__(self):
            super().__init__()
            self.exception = None

        def on_exception(self, trainer, pl_module, exception):
            self.exception = exception

    interrupt_callback = InterruptCallback()
    handle_interrupt_callback = HandleInterruptCallback()

    trainer = Trainer(
        callbacks=[interrupt_callback, handle_interrupt_callback],
        max_epochs=1,
        limit_val_batches=0.1,
        limit_train_batches=0.2,
        enable_progress_bar=False,
        logger=False,
        default_root_dir=tmp_path,
    )
    assert not trainer.interrupted
    assert handle_interrupt_callback.exception is None
    with pytest.raises(SystemExit):
        trainer.fit(model)
    assert trainer.interrupted
    assert isinstance(handle_interrupt_callback.exception, KeyboardInterrupt)
    with pytest.raises(MisconfigurationException):
        trainer.test(model)
    assert trainer.interrupted
    assert isinstance(handle_interrupt_callback.exception, MisconfigurationException)
Test the on_exception callback hook and the trainer interrupted flag.
tests/tests_pytorch/trainer/test_trainer.py