Repository: pytorch/ignite

Issue:
Bug with ProgressBar with TerminateOnNan
If we attach `ProgressBar` and `TerminateOnNaN` handlers to a trainer and `TerminateOnNan` stops training on the first iteration. We have the following error:

```python
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-36-b4ac10e6ccc4> in <module>
----> 1 trainer.run(train_ab_loader, max_epochs=200)

/opt/conda/lib/python3.7/site-packages/ignite/engine/engine.py in run(self, data, max_epochs)
    357         except BaseException as e:
    358             self._logger.error("Engine run is terminating due to exception: %s.", str(e))
--> 359             self._handle_exception(e)
    360 
    361         return self.state

/opt/conda/lib/python3.7/site-packages/ignite/engine/engine.py in _handle_exception(self, e)
    322             self._fire_event(Events.EXCEPTION_RAISED, e)
    323         else:
--> 324             raise e
    325 
    326     def run(self, data, max_epochs=1):

/opt/conda/lib/python3.7/site-packages/ignite/engine/engine.py in run(self, data, max_epochs)
    350                 self._fire_event(Events.EPOCH_COMPLETED)
    351 
--> 352             self._fire_event(Events.COMPLETED)
    353             time_taken = time.time() - start_time
    354             hours, mins, secs = _to_hours_mins_secs(time_taken)

/opt/conda/lib/python3.7/site-packages/ignite/engine/engine.py in _fire_event(self, event_name, *event_args, **event_kwargs)
    257             for func, args, kwargs in self._event_handlers[event_name]:
    258                 kwargs.update(event_kwargs)
--> 259                 func(self, *(event_args + args), **kwargs)
    260 
    261     def fire_event(self, event_name):

/opt/conda/lib/python3.7/site-packages/ignite/contrib/handlers/tqdm_logger.py in _close(self, engine)
    115 
    116     def _close(self, engine):
--> 117         self.pbar.close()
    118         self.pbar = None
    119 

AttributeError: 'NoneType' object has no attribute 'close'
```


Discussion:

Resolving patch:
diff --git a/ignite/contrib/handlers/tqdm_logger.py b/ignite/contrib/handlers/tqdm_logger.py
--- a/ignite/contrib/handlers/tqdm_logger.py
+++ b/ignite/contrib/handlers/tqdm_logger.py
@@ -114,7 +114,8 @@ def _reset(self, pbar_total):
         )
 
     def _close(self, engine):
-        self.pbar.close()
+        if self.pbar:
+            self.pbar.close()
         self.pbar = None
 
     @staticmethod


Test patch:
diff --git a/tests/ignite/contrib/handlers/test_tqdm_logger.py b/tests/ignite/contrib/handlers/test_tqdm_logger.py
--- a/tests/ignite/contrib/handlers/test_tqdm_logger.py
+++ b/tests/ignite/contrib/handlers/test_tqdm_logger.py
@@ -7,6 +7,7 @@
 from ignite.engine import Engine, Events
 from ignite.metrics import Accuracy
 from ignite.contrib.handlers import CustomPeriodicEvent
+from ignite.handlers import TerminateOnNan
 
 
 def update_fn(engine, batch):
@@ -261,3 +262,31 @@ def test_pbar_on_custom_events(capsys):
 
     with pytest.raises(ValueError, match=r"Logging and closing events should be only ignite.engine.Events"):
         pbar.attach(engine, event_name=cpe.Events.ITERATIONS_15_COMPLETED, closing_event_name=Events.EPOCH_COMPLETED)
+
+
+def test_pbar_with_nan_input():
+    def update(engine, batch):
+        x = batch
+        return x.item()
+
+    def create_engine():
+        engine = Engine(update)
+        pbar = ProgressBar()
+
+        engine.add_event_handler(Events.ITERATION_COMPLETED, TerminateOnNan())
+        pbar.attach(engine, event_name=Events.EPOCH_COMPLETED, closing_event_name=Events.COMPLETED)
+        return engine
+
+    data = torch.from_numpy(np.array([np.nan] * 25))
+    engine = create_engine()
+    engine.run(data)
+    assert engine.should_terminate
+    assert engine.state.iteration == 1
+    assert engine.state.epoch == 1
+
+    data = torch.from_numpy(np.array([1] * 1000 + [np.nan] * 25))
+    engine = create_engine()
+    engine.run(data)
+    assert engine.should_terminate
+    assert engine.state.iteration == 1001
+    assert engine.state.epoch == 1