# Buggy code
def train(self):
    # add signal handlers for process kills
    # def _signal_kill_handler(*args):
    #     return TrainerTrainLoopMixin.run_training_teardown(self)
    #
    # orig_signal_handlers = {}
    # for sig_name in SIGNAL_TERMINATE:
    #     orig_signal_handlers[sig_name] = signal.signal(getattr(signal, sig_name),
    #                                                    _signal_kill_handler)

    # get model
    model = self.get_model()

    # enable train mode
    model.train()

    # enable gradients
    torch.set_grad_enabled(True)

    # load data
    # if reload_dataloaders_every_epoch, this is moved to the epoch loop
    if not self.reload_dataloaders_every_epoch:
        self.reset_train_dataloader(model)

    if model.val_dataloader is not None:
        self.reset_val_dataloader(model)

    # Train start events
    with self.profiler.profile("on_train_start"):
        # callbacks
        self.on_train_start()
        # model hooks
        model.on_train_start()

    try:
        # run all epochs
        for epoch in range(self.current_epoch, self.max_epochs):
            # reset train dataloader
            if self.reload_dataloaders_every_epoch:
                self.reset_train_dataloader(model)
            # set seed for distributed sampler (enables shuffling for each epoch)
            if (
                (self.use_ddp or self.use_horovod)
                and hasattr(self.train_dataloader, "sampler")
                and hasattr(self.train_dataloader.sampler, "set_epoch")
            ):
                self.train_dataloader.sampler.set_epoch(epoch)

            # update training progress in trainer and model
            model.current_epoch = epoch
            self.current_epoch = epoch

            # changing gradient according accumulation_scheduler
            self.accumulation_scheduler.on_epoch_start(self, self.get_model())

            # stores accumulated grad fractions per batch
            self.batch_loss_value = TensorRunningAccum(
                window_length=self.accumulate_grad_batches
            )

            # -----------------
            # RUN TNG EPOCH
            # -----------------
            self.run_training_epoch()

            if self.max_steps and self.max_steps <= self.global_step:
                self.run_training_teardown()
                return

            # update LR schedulers
            self.update_learning_rates(interval="epoch")

            # early stopping
            met_min_epochs = epoch >= self.min_epochs - 1
            met_min_steps = (
                self.global_step >= self.min_steps if self.min_steps else True
            )

            if self.should_stop:
                if (met_min_epochs and met_min_steps) or self.fast_dev_run:
                    self.run_training_teardown()
                    return
                else:
                    log.info(
                        "Trainer was signaled to stop but required minimum epochs"
                        f" ({self.min_epochs}) or minimum steps ({self.min_steps}) has"
                        " not been met. Training will continue..."
                    )

        self.run_training_teardown()

    except KeyboardInterrupt:
        rank_zero_warn("Detected KeyboardInterrupt, attempting graceful shutdown...")

        # user could press ctrl+c many times... only shutdown once
        if not self.interrupted:
            self.interrupted = True
            self.on_keyboard_interrupt()

            self.run_training_teardown()


# Traceback (IndexError)
Traceback (most recent call last):
File "/home/luca/Repositories/set-operations/src/run_experiment.py", line 73, in <module>
trainer.fit(model,)
File "/home/luca/.cache/pypoetry/virtualenvs/set-operations-GbjOlTQ2-py3.7/lib/python3.7/site-packages/pytorch_lightning/trainer/trainer.py", line 979, in fit
self.single_gpu_train(model)
File "/home/luca/.cache/pypoetry/virtualenvs/set-operations-GbjOlTQ2-py3.7/lib/python3.7/site-packages/pytorch_lightning/trainer/distrib_parts.py", line 185, in single_gpu_train
self.run_pretrain_routine(model)
File "/home/luca/.cache/pypoetry/virtualenvs/set-operations-GbjOlTQ2-py3.7/lib/python3.7/site-packages/pytorch_lightning/trainer/trainer.py", line 1156, in run_pretrain_routine
self.train()
File "/home/luca/.cache/pypoetry/virtualenvs/set-operations-GbjOlTQ2-py3.7/lib/python3.7/site-packages/pytorch_lightning/trainer/training_loop.py", line 370, in train
self.run_training_epoch()
File "/home/luca/.cache/pypoetry/virtualenvs/set-operations-GbjOlTQ2-py3.7/lib/python3.7/site-packages/pytorch_lightning/trainer/training_loop.py", line 470, in run_training_epoch
self.run_evaluation(test_mode=False)
File "/home/luca/.cache/pypoetry/virtualenvs/set-operations-GbjOlTQ2-py3.7/lib/python3.7/site-packages/pytorch_lightning/trainer/evaluation_loop.py", line 409, in run_evaluation
eval_results = self._evaluate(self.model, dataloaders, max_batches, test_mode)
File "/home/luca/.cache/pypoetry/virtualenvs/set-operations-GbjOlTQ2-py3.7/lib/python3.7/site-packages/pytorch_lightning/trainer/evaluation_loop.py", line 270, in _evaluate
dl_max_batches = max_batches[dataloader_idx]
IndexError: list index out of range

Exception ignored in: <function tqdm.__del__ at 0x7fe5848ba710>
Traceback (most recent call last):
File "/home/luca/.cache/pypoetry/virtualenvs/set-operations-GbjOlTQ2-py3.7/lib/python3.7/site-packages/tqdm/std.py", line 1086, in __del__
File "/home/luca/.cache/pypoetry/virtualenvs/set-operations-GbjOlTQ2-py3.7/lib/python3.7/site-packages/tqdm/std.py", line 1293, in close
File "/home/luca/.cache/pypoetry/virtualenvs/set-operations-GbjOlTQ2-py3.7/lib/python3.7/site-packages/tqdm/std.py", line 1471, in display
File "/home/luca/.cache/pypoetry/virtualenvs/set-operations-GbjOlTQ2-py3.7/lib/python3.7/site-packages/tqdm/std.py", line 1089, in __repr__
File "/home/luca/.cache/pypoetry/virtualenvs/set-operations-GbjOlTQ2-py3.7/lib/python3.7/site-packages/tqdm/std.py", line 1433, in format_dict
TypeError: cannot unpack non-iterable NoneType object

Process finished with exit code 1

# Fixed code
def train(self):
    # add signal handlers for process kills
    # def _signal_kill_handler(*args):
    #     return TrainerTrainLoopMixin.run_training_teardown(self)
    #
    # orig_signal_handlers = {}
    # for sig_name in SIGNAL_TERMINATE:
    #     orig_signal_handlers[sig_name] = signal.signal(getattr(signal, sig_name),
    #                                                    _signal_kill_handler)

    # get model
    model = self.get_model()

    # enable train mode
    model.train()

    # enable gradients
    torch.set_grad_enabled(True)

    # load data
    # if reload_dataloaders_every_epoch, this is moved to the epoch loop
    if not self.reload_dataloaders_every_epoch:
        self.reset_train_dataloader(model)

    if model.val_dataloader is not None:
        self.reset_val_dataloader(model)

    # Train start events
    with self.profiler.profile("on_train_start"):
        # callbacks
        self.on_train_start()
        # model hooks
        model.on_train_start()

    try:
        # run all epochs
        for epoch in range(self.current_epoch, self.max_epochs):
            # reset train dataloader
            if self.reload_dataloaders_every_epoch:
                self.reset_train_dataloader(model)
            # set seed for distributed sampler (enables shuffling for each epoch)
            if (
                (self.use_ddp or self.use_horovod)
                and hasattr(self.train_dataloader, "sampler")
                and hasattr(self.train_dataloader.sampler, "set_epoch")
            ):
                self.train_dataloader.sampler.set_epoch(epoch)

            # update training progress in trainer and model
            model.current_epoch = epoch
            self.current_epoch = epoch

            # changing gradient according accumulation_scheduler
            self.accumulation_scheduler.on_epoch_start(self, self.get_model())

            # stores accumulated grad fractions per batch
            self.batch_loss_value = TensorRunningAccum(
                window_length=self.accumulate_grad_batches
            )

            # -----------------
            # RUN TNG EPOCH
            # -----------------
            self.run_training_epoch()

            if self.max_steps and self.max_steps <= self.global_step:
                self.run_training_teardown()
                return

            # update LR schedulers
            self.update_learning_rates(interval="epoch")

            # early stopping
            met_min_epochs = epoch >= self.min_epochs - 1
            met_min_steps = (
                self.global_step >= self.min_steps if self.min_steps else True
            )

            if self.should_stop:
                if met_min_epochs and met_min_steps:
                    self.run_training_teardown()
                    return
                else:
                    log.info(
                        "Trainer was signaled to stop but required minimum epochs"
                        f" ({self.min_epochs}) or minimum steps ({self.min_steps}) has"
                        " not been met. Training will continue..."
                    )

        self.run_training_teardown()

    except KeyboardInterrupt:
        rank_zero_warn("Detected KeyboardInterrupt, attempting graceful shutdown...")

        # user could press ctrl+c many times... only shutdown once
        if not self.interrupted:
            self.interrupted = True
            self.on_keyboard_interrupt()

            self.run_training_teardown()