We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN 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'
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ignite/contrib/handlers/tqdm_logger.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 import numbers
3 import warnings
4 
5 import torch
6 
7 from ignite.engine import Events
8 
9 from ignite.contrib.handlers.base_logger import BaseLogger, BaseOutputHandler
10 
11 
12 class ProgressBar(BaseLogger):
13     """
14     TQDM progress bar handler to log training progress and computed metrics.
15 
16     Args:
17         persist (bool, optional): set to ``True`` to persist the progress bar after completion (default = ``False``)
18         bar_format  (str, optional): Specify a custom bar string formatting. May impact performance.
19             [default: '{desc}[{n_fmt}/{total_fmt}] {percentage:3.0f}%|{bar}{postfix} [{elapsed}<{remaining}]'].
20             Set to ``None`` to use ``tqdm`` default bar formatting: '{l_bar}{bar}{r_bar}', where
21             l_bar='{desc}: {percentage:3.0f}%|' and
22             r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_fmt}{postfix}]'. For more details on the
23             formatting, see `tqdm docs <https://tqdm.github.io/docs/tqdm/>`_.
24         **tqdm_kwargs: kwargs passed to tqdm progress bar.
25             By default, progress bar description displays "Epoch [5/10]" where 5 is the current epoch and 10 is the
26             number of epochs. If tqdm_kwargs defines `desc`, e.g. "Predictions", than the description is
27             "Predictions [5/10]" if number of epochs is more than one otherwise it is simply "Predictions".
28 
29     Examples:
30 
31         Simple progress bar
32 
33         .. code-block:: python
34 
35             trainer = create_supervised_trainer(model, optimizer, loss)
36 
37             pbar = ProgressBar()
38             pbar.attach(trainer)
39 
40             # Progress bar will looks like
41             # Epoch [2/50]: [64/128]  50%|█████      [06:17<12:34]
42 
43         Attach metrics that already have been computed at :attr:`~ignite.engine.Events.ITERATION_COMPLETED`
44         (such as :class:`~ignite.metrics.RunningAverage`)
45 
46         .. code-block:: python
47 
48             trainer = create_supervised_trainer(model, optimizer, loss)
49 
50             RunningAverage(output_transform=lambda x: x).attach(trainer, 'loss')
51 
52             pbar = ProgressBar()
53             pbar.attach(trainer, ['loss'])
54 
55             # Progress bar will looks like
56             # Epoch [2/50]: [64/128]  50%|█████      , loss=12.34e-02 [06:17<12:34]
57 
58         Directly attach the engine's output
59 
60         .. code-block:: python
61 
62             trainer = create_supervised_trainer(model, optimizer, loss)
63 
64             pbar = ProgressBar()
65             pbar.attach(trainer, output_transform=lambda x: {'loss': x})
66 
67             # Progress bar will looks like
68             # Epoch [2/50]: [64/128]  50%|█████      , loss=12.34e-02 [06:17<12:34]
69 
70     Note:
71         When adding attaching the progress bar to an engine, it is recommend that you replace
72         every print operation in the engine's handlers triggered every iteration with
73         ``pbar.log_message`` to guarantee the correct format of the stdout.
74 
75     Note:
76         When using inside jupyter notebook, `ProgressBar` automatically uses `tqdm_notebook`. For correct rendering,
77         please install `ipywidgets <https://ipywidgets.readthedocs.io/en/stable/user_install.html#installation>`_.
78         Due to `tqdm notebook bugs <https://github.com/tqdm/tqdm/issues/594>`_, bar format may be needed to be set
79         to an empty string value.
80 
81     """
82 
83     events_order = [
84         Events.STARTED,
85         Events.EPOCH_STARTED,
86         Events.ITERATION_STARTED,
87         Events.ITERATION_COMPLETED,
88         Events.EPOCH_COMPLETED,
89         Events.COMPLETED
90     ]
91 
92     def __init__(self, persist=False,
93                  bar_format='{desc}[{n_fmt}/{total_fmt}] {percentage:3.0f}%|{bar}{postfix} [{elapsed}<{remaining}]',
94                  **tqdm_kwargs):
95 
96         try:
97             from tqdm.autonotebook import tqdm
98         except ImportError:
99             raise RuntimeError("This contrib module requires tqdm to be installed. "
100                                "Please install it with command: \n pip install tqdm")
101 
102         self.pbar_cls = tqdm
103         self.pbar = None
104         self.persist = persist
105         self.bar_format = bar_format
106         self.tqdm_kwargs = tqdm_kwargs
107 
108     def _reset(self, pbar_total):
109         self.pbar = self.pbar_cls(
110             total=pbar_total,
111             leave=self.persist,
112             bar_format=self.bar_format,
113             **self.tqdm_kwargs
114         )
115 
116     def _close(self, engine):
117         self.pbar.close()
118         self.pbar = None
119 
120     @staticmethod
121     def _compare_lt(event1, event2):
122         i1 = ProgressBar.events_order.index(event1)
123         i2 = ProgressBar.events_order.index(event2)
124         return i1 < i2
125 
126     @staticmethod
127     def log_message(message):
128         """
129         Logs a message, preserving the progress bar correct output format.
130 
131         Args:
132             message (str): string you wish to log.
133         """
134         from tqdm import tqdm
135         tqdm.write(message)
136 
137     def attach(self, engine, metric_names=None, output_transform=None,
138                event_name=Events.ITERATION_COMPLETED,
139                closing_event_name=Events.EPOCH_COMPLETED):
140         """
141         Attaches the progress bar to an engine object.
142 
143         Args:
144             engine (Engine): engine object.
145             metric_names (list, optional): list of the metrics names to log as the bar progresses
146             output_transform (callable, optional): a function to select what you want to print from the engine's
147                 output. This function may return either a dictionary with entries in the format of ``{name: value}``,
148                 or a single scalar, which will be displayed with the default name `output`.
149             event_name: event's name on which the progress bar advances. Valid events are from
150                 :class:`~ignite.engine.Events`.
151             closing_event_name: event's name on which the progress bar is closed. Valid events are from
152                 :class:`~ignite.engine.Events`.
153         """
154         desc = self.tqdm_kwargs.get("desc", "Epoch")
155 
156         if not (event_name in Events and closing_event_name in Events):
157             raise ValueError("Logging and closing events should be only ignite.engine.Events")
158 
159         if not self._compare_lt(event_name, closing_event_name):
160             raise ValueError("Logging event {} should be called before closing event {}"
161                              .format(event_name, closing_event_name))
162 
163         log_handler = _OutputHandler(desc, metric_names, output_transform,
164                                      event_name=event_name,
165                                      closing_event_name=closing_event_name)
166         super(ProgressBar, self).attach(engine, log_handler, event_name)
167         engine.add_event_handler(closing_event_name, self._close)
168 
169 
170 class _OutputHandler(BaseOutputHandler):
171     """Helper handler to log engine's output and/or metrics
172 
173     Args:
174         description (str): progress bar description.
175         metric_names (list of str, optional): list of metric names to plot.
176         output_transform (callable, optional): output transform function to prepare `engine.state.output` as a number.
177             For example, `output_transform = lambda output: output`
178             This function can also return a dictionary, e.g `{'loss': loss1, `another_loss`: loss2}` to label the plot
179             with corresponding keys.
180         event_name: event's name on which the progress bar advances. Valid events are from
181             :class:`~ignite.engine.Events` or any `event_name` added by
182             :meth:`~ignite.engine.Engine.register_events`.
183         closing_event_name: event's name on which the progress bar is closed. Valid events are from
184             :class:`~ignite.engine.Events` or any `event_name` added by
185             :meth:`~ignite.engine.Engine.register_events`.
186 
187     """
188     def __init__(self, description, metric_names=None, output_transform=None,
189                  event_name=Events.ITERATION_COMPLETED,
190                  closing_event_name=Events.EPOCH_COMPLETED):
191         if metric_names is None and output_transform is None:
192             # This helps to avoid 'Either metric_names or output_transform should be defined' of BaseOutputHandler
193             metric_names = []
194         super(_OutputHandler, self).__init__(description, metric_names, output_transform, another_engine=None)
195         self.event_name = event_name
196         self.closing_event_name = closing_event_name
197 
198     @staticmethod
199     def get_max_number_events(event_name, engine):
200         if event_name in (Events.ITERATION_STARTED, Events.ITERATION_COMPLETED):
201             return len(engine.state.dataloader)
202         if event_name in (Events.EPOCH_STARTED, Events.EPOCH_COMPLETED):
203             return engine.state.max_epochs
204         return 1
205 
206     def __call__(self, engine, logger, event_name):
207 
208         if logger.pbar is None:
209             logger._reset(pbar_total=self.get_max_number_events(self.event_name, engine))
210 
211         desc = self.tag
212         max_num_of_closing_events = self.get_max_number_events(self.closing_event_name, engine)
213         if max_num_of_closing_events > 1:
214             global_step = engine.state.get_event_attrib_value(self.closing_event_name)
215             desc += " [{}/{}]".format(global_step, max_num_of_closing_events)
216         logger.pbar.set_description(desc)
217 
218         metrics = self._setup_output_metrics(engine)
219 
220         rendered_metrics = {}
221         for key, value in metrics.items():
222             if isinstance(value, numbers.Number) or \
223                     isinstance(value, torch.Tensor) and value.ndimension() == 0:
224                 rendered_metrics[key] = "{:.2e}".format(value)
225             elif isinstance(value, torch.Tensor) and value.ndimension() == 1:
226                 for i, v in enumerate(value):
227                     k = "{}_{}".format(key, i)
228                     rendered_metrics[k] = "{:.2e}".format(v)
229             else:
230                 warnings.warn("ProgressBar can not log "
231                               "metrics value type {}".format(type(value)))
232 
233         if rendered_metrics:
234             logger.pbar.set_postfix(**rendered_metrics)
235 
236         logger.pbar.update()
237
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

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 _close(self, engine):
-        self.pbar.close()
+        if self.pbar:
+            self.pbar.close()
         self.pbar = None
 
     @staticmethod

{"golden_diff": "diff --git a/ignite/contrib/handlers/tqdm_logger.py b/ignite/contrib/handlers/tqdm_logger.py\n--- a/ignite/contrib/handlers/tqdm_logger.py\n+++ b/ignite/contrib/handlers/tqdm_logger.py\n@@ -114,7 +114,8 @@\n         )\n \n     def _close(self, engine):\n-        self.pbar.close()\n+        if self.pbar:\n+            self.pbar.close()\n         self.pbar = None\n \n     @staticmethod\n", "issue": "Bug with ProgressBar with TerminateOnNan\nIf we attach `ProgressBar` and `TerminateOnNaN` handlers to a trainer and `TerminateOnNan` stops training on the first iteration. We have the following error:\r\n\r\n```python\r\n---------------------------------------------------------------------------\r\nAttributeError                            Traceback (most recent call last)\r\n<ipython-input-36-b4ac10e6ccc4> in <module>\r\n----> 1 trainer.run(train_ab_loader, max_epochs=200)\r\n\r\n/opt/conda/lib/python3.7/site-packages/ignite/engine/engine.py in run(self, data, max_epochs)\r\n    357         except BaseException as e:\r\n    358             self._logger.error(\"Engine run is terminating due to exception: %s.\", str(e))\r\n--> 359             self._handle_exception(e)\r\n    360 \r\n    361         return self.state\r\n\r\n/opt/conda/lib/python3.7/site-packages/ignite/engine/engine.py in _handle_exception(self, e)\r\n    322             self._fire_event(Events.EXCEPTION_RAISED, e)\r\n    323         else:\r\n--> 324             raise e\r\n    325 \r\n    326     def run(self, data, max_epochs=1):\r\n\r\n/opt/conda/lib/python3.7/site-packages/ignite/engine/engine.py in run(self, data, max_epochs)\r\n    350                 self._fire_event(Events.EPOCH_COMPLETED)\r\n    351 \r\n--> 352             self._fire_event(Events.COMPLETED)\r\n    353             time_taken = time.time() - start_time\r\n    354             hours, mins, secs = _to_hours_mins_secs(time_taken)\r\n\r\n/opt/conda/lib/python3.7/site-packages/ignite/engine/engine.py in _fire_event(self, event_name, *event_args, **event_kwargs)\r\n    257             for func, args, kwargs in self._event_handlers[event_name]:\r\n    258                 kwargs.update(event_kwargs)\r\n--> 259                 func(self, *(event_args + args), **kwargs)\r\n    260 \r\n    261     def fire_event(self, event_name):\r\n\r\n/opt/conda/lib/python3.7/site-packages/ignite/contrib/handlers/tqdm_logger.py in _close(self, engine)\r\n    115 \r\n    116     def _close(self, engine):\r\n--> 117         self.pbar.close()\r\n    118         self.pbar = None\r\n    119 \r\n\r\nAttributeError: 'NoneType' object has no attribute 'close'\r\n```\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\nimport numbers\nimport warnings\n\nimport torch\n\nfrom ignite.engine import Events\n\nfrom ignite.contrib.handlers.base_logger import BaseLogger, BaseOutputHandler\n\n\nclass ProgressBar(BaseLogger):\n    \"\"\"\n    TQDM progress bar handler to log training progress and computed metrics.\n\n    Args:\n        persist (bool, optional): set to ``True`` to persist the progress bar after completion (default = ``False``)\n        bar_format  (str, optional): Specify a custom bar string formatting. May impact performance.\n            [default: '{desc}[{n_fmt}/{total_fmt}] {percentage:3.0f}%|{bar}{postfix} [{elapsed}<{remaining}]'].\n            Set to ``None`` to use ``tqdm`` default bar formatting: '{l_bar}{bar}{r_bar}', where\n            l_bar='{desc}: {percentage:3.0f}%|' and\n            r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_fmt}{postfix}]'. For more details on the\n            formatting, see `tqdm docs <https://tqdm.github.io/docs/tqdm/>`_.\n        **tqdm_kwargs: kwargs passed to tqdm progress bar.\n            By default, progress bar description displays \"Epoch [5/10]\" where 5 is the current epoch and 10 is the\n            number of epochs. If tqdm_kwargs defines `desc`, e.g. \"Predictions\", than the description is\n            \"Predictions [5/10]\" if number of epochs is more than one otherwise it is simply \"Predictions\".\n\n    Examples:\n\n        Simple progress bar\n\n        .. code-block:: python\n\n            trainer = create_supervised_trainer(model, optimizer, loss)\n\n            pbar = ProgressBar()\n            pbar.attach(trainer)\n\n            # Progress bar will looks like\n            # Epoch [2/50]: [64/128]  50%|\u2588\u2588\u2588\u2588\u2588      [06:17<12:34]\n\n        Attach metrics that already have been computed at :attr:`~ignite.engine.Events.ITERATION_COMPLETED`\n        (such as :class:`~ignite.metrics.RunningAverage`)\n\n        .. code-block:: python\n\n            trainer = create_supervised_trainer(model, optimizer, loss)\n\n            RunningAverage(output_transform=lambda x: x).attach(trainer, 'loss')\n\n            pbar = ProgressBar()\n            pbar.attach(trainer, ['loss'])\n\n            # Progress bar will looks like\n            # Epoch [2/50]: [64/128]  50%|\u2588\u2588\u2588\u2588\u2588      , loss=12.34e-02 [06:17<12:34]\n\n        Directly attach the engine's output\n\n        .. code-block:: python\n\n            trainer = create_supervised_trainer(model, optimizer, loss)\n\n            pbar = ProgressBar()\n            pbar.attach(trainer, output_transform=lambda x: {'loss': x})\n\n            # Progress bar will looks like\n            # Epoch [2/50]: [64/128]  50%|\u2588\u2588\u2588\u2588\u2588      , loss=12.34e-02 [06:17<12:34]\n\n    Note:\n        When adding attaching the progress bar to an engine, it is recommend that you replace\n        every print operation in the engine's handlers triggered every iteration with\n        ``pbar.log_message`` to guarantee the correct format of the stdout.\n\n    Note:\n        When using inside jupyter notebook, `ProgressBar` automatically uses `tqdm_notebook`. For correct rendering,\n        please install `ipywidgets <https://ipywidgets.readthedocs.io/en/stable/user_install.html#installation>`_.\n        Due to `tqdm notebook bugs <https://github.com/tqdm/tqdm/issues/594>`_, bar format may be needed to be set\n        to an empty string value.\n\n    \"\"\"\n\n    events_order = [\n        Events.STARTED,\n        Events.EPOCH_STARTED,\n        Events.ITERATION_STARTED,\n        Events.ITERATION_COMPLETED,\n        Events.EPOCH_COMPLETED,\n        Events.COMPLETED\n    ]\n\n    def __init__(self, persist=False,\n                 bar_format='{desc}[{n_fmt}/{total_fmt}] {percentage:3.0f}%|{bar}{postfix} [{elapsed}<{remaining}]',\n                 **tqdm_kwargs):\n\n        try:\n            from tqdm.autonotebook import tqdm\n        except ImportError:\n            raise RuntimeError(\"This contrib module requires tqdm to be installed. \"\n                               \"Please install it with command: \\n pip install tqdm\")\n\n        self.pbar_cls = tqdm\n        self.pbar = None\n        self.persist = persist\n        self.bar_format = bar_format\n        self.tqdm_kwargs = tqdm_kwargs\n\n    def _reset(self, pbar_total):\n        self.pbar = self.pbar_cls(\n            total=pbar_total,\n            leave=self.persist,\n            bar_format=self.bar_format,\n            **self.tqdm_kwargs\n        )\n\n    def _close(self, engine):\n        self.pbar.close()\n        self.pbar = None\n\n    @staticmethod\n    def _compare_lt(event1, event2):\n        i1 = ProgressBar.events_order.index(event1)\n        i2 = ProgressBar.events_order.index(event2)\n        return i1 < i2\n\n    @staticmethod\n    def log_message(message):\n        \"\"\"\n        Logs a message, preserving the progress bar correct output format.\n\n        Args:\n            message (str): string you wish to log.\n        \"\"\"\n        from tqdm import tqdm\n        tqdm.write(message)\n\n    def attach(self, engine, metric_names=None, output_transform=None,\n               event_name=Events.ITERATION_COMPLETED,\n               closing_event_name=Events.EPOCH_COMPLETED):\n        \"\"\"\n        Attaches the progress bar to an engine object.\n\n        Args:\n            engine (Engine): engine object.\n            metric_names (list, optional): list of the metrics names to log as the bar progresses\n            output_transform (callable, optional): a function to select what you want to print from the engine's\n                output. This function may return either a dictionary with entries in the format of ``{name: value}``,\n                or a single scalar, which will be displayed with the default name `output`.\n            event_name: event's name on which the progress bar advances. Valid events are from\n                :class:`~ignite.engine.Events`.\n            closing_event_name: event's name on which the progress bar is closed. Valid events are from\n                :class:`~ignite.engine.Events`.\n        \"\"\"\n        desc = self.tqdm_kwargs.get(\"desc\", \"Epoch\")\n\n        if not (event_name in Events and closing_event_name in Events):\n            raise ValueError(\"Logging and closing events should be only ignite.engine.Events\")\n\n        if not self._compare_lt(event_name, closing_event_name):\n            raise ValueError(\"Logging event {} should be called before closing event {}\"\n                             .format(event_name, closing_event_name))\n\n        log_handler = _OutputHandler(desc, metric_names, output_transform,\n                                     event_name=event_name,\n                                     closing_event_name=closing_event_name)\n        super(ProgressBar, self).attach(engine, log_handler, event_name)\n        engine.add_event_handler(closing_event_name, self._close)\n\n\nclass _OutputHandler(BaseOutputHandler):\n    \"\"\"Helper handler to log engine's output and/or metrics\n\n    Args:\n        description (str): progress bar description.\n        metric_names (list of str, optional): list of metric names to plot.\n        output_transform (callable, optional): output transform function to prepare `engine.state.output` as a number.\n            For example, `output_transform = lambda output: output`\n            This function can also return a dictionary, e.g `{'loss': loss1, `another_loss`: loss2}` to label the plot\n            with corresponding keys.\n        event_name: event's name on which the progress bar advances. Valid events are from\n            :class:`~ignite.engine.Events` or any `event_name` added by\n            :meth:`~ignite.engine.Engine.register_events`.\n        closing_event_name: event's name on which the progress bar is closed. Valid events are from\n            :class:`~ignite.engine.Events` or any `event_name` added by\n            :meth:`~ignite.engine.Engine.register_events`.\n\n    \"\"\"\n    def __init__(self, description, metric_names=None, output_transform=None,\n                 event_name=Events.ITERATION_COMPLETED,\n                 closing_event_name=Events.EPOCH_COMPLETED):\n        if metric_names is None and output_transform is None:\n            # This helps to avoid 'Either metric_names or output_transform should be defined' of BaseOutputHandler\n            metric_names = []\n        super(_OutputHandler, self).__init__(description, metric_names, output_transform, another_engine=None)\n        self.event_name = event_name\n        self.closing_event_name = closing_event_name\n\n    @staticmethod\n    def get_max_number_events(event_name, engine):\n        if event_name in (Events.ITERATION_STARTED, Events.ITERATION_COMPLETED):\n            return len(engine.state.dataloader)\n        if event_name in (Events.EPOCH_STARTED, Events.EPOCH_COMPLETED):\n            return engine.state.max_epochs\n        return 1\n\n    def __call__(self, engine, logger, event_name):\n\n        if logger.pbar is None:\n            logger._reset(pbar_total=self.get_max_number_events(self.event_name, engine))\n\n        desc = self.tag\n        max_num_of_closing_events = self.get_max_number_events(self.closing_event_name, engine)\n        if max_num_of_closing_events > 1:\n            global_step = engine.state.get_event_attrib_value(self.closing_event_name)\n            desc += \" [{}/{}]\".format(global_step, max_num_of_closing_events)\n        logger.pbar.set_description(desc)\n\n        metrics = self._setup_output_metrics(engine)\n\n        rendered_metrics = {}\n        for key, value in metrics.items():\n            if isinstance(value, numbers.Number) or \\\n                    isinstance(value, torch.Tensor) and value.ndimension() == 0:\n                rendered_metrics[key] = \"{:.2e}\".format(value)\n            elif isinstance(value, torch.Tensor) and value.ndimension() == 1:\n                for i, v in enumerate(value):\n                    k = \"{}_{}\".format(key, i)\n                    rendered_metrics[k] = \"{:.2e}\".format(v)\n            else:\n                warnings.warn(\"ProgressBar can not log \"\n                              \"metrics value type {}\".format(type(value)))\n\n        if rendered_metrics:\n            logger.pbar.set_postfix(**rendered_metrics)\n\n        logger.pbar.update()\n", "path": "ignite/contrib/handlers/tqdm_logger.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\nimport numbers\nimport warnings\n\nimport torch\n\nfrom ignite.engine import Events\n\nfrom ignite.contrib.handlers.base_logger import BaseLogger, BaseOutputHandler\n\n\nclass ProgressBar(BaseLogger):\n    \"\"\"\n    TQDM progress bar handler to log training progress and computed metrics.\n\n    Args:\n        persist (bool, optional): set to ``True`` to persist the progress bar after completion (default = ``False``)\n        bar_format  (str, optional): Specify a custom bar string formatting. May impact performance.\n            [default: '{desc}[{n_fmt}/{total_fmt}] {percentage:3.0f}%|{bar}{postfix} [{elapsed}<{remaining}]'].\n            Set to ``None`` to use ``tqdm`` default bar formatting: '{l_bar}{bar}{r_bar}', where\n            l_bar='{desc}: {percentage:3.0f}%|' and\n            r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_fmt}{postfix}]'. For more details on the\n            formatting, see `tqdm docs <https://tqdm.github.io/docs/tqdm/>`_.\n        **tqdm_kwargs: kwargs passed to tqdm progress bar.\n            By default, progress bar description displays \"Epoch [5/10]\" where 5 is the current epoch and 10 is the\n            number of epochs. If tqdm_kwargs defines `desc`, e.g. \"Predictions\", than the description is\n            \"Predictions [5/10]\" if number of epochs is more than one otherwise it is simply \"Predictions\".\n\n    Examples:\n\n        Simple progress bar\n\n        .. code-block:: python\n\n            trainer = create_supervised_trainer(model, optimizer, loss)\n\n            pbar = ProgressBar()\n            pbar.attach(trainer)\n\n            # Progress bar will looks like\n            # Epoch [2/50]: [64/128]  50%|\u2588\u2588\u2588\u2588\u2588      [06:17<12:34]\n\n        Attach metrics that already have been computed at :attr:`~ignite.engine.Events.ITERATION_COMPLETED`\n        (such as :class:`~ignite.metrics.RunningAverage`)\n\n        .. code-block:: python\n\n            trainer = create_supervised_trainer(model, optimizer, loss)\n\n            RunningAverage(output_transform=lambda x: x).attach(trainer, 'loss')\n\n            pbar = ProgressBar()\n            pbar.attach(trainer, ['loss'])\n\n            # Progress bar will looks like\n            # Epoch [2/50]: [64/128]  50%|\u2588\u2588\u2588\u2588\u2588      , loss=12.34e-02 [06:17<12:34]\n\n        Directly attach the engine's output\n\n        .. code-block:: python\n\n            trainer = create_supervised_trainer(model, optimizer, loss)\n\n            pbar = ProgressBar()\n            pbar.attach(trainer, output_transform=lambda x: {'loss': x})\n\n            # Progress bar will looks like\n            # Epoch [2/50]: [64/128]  50%|\u2588\u2588\u2588\u2588\u2588      , loss=12.34e-02 [06:17<12:34]\n\n    Note:\n        When adding attaching the progress bar to an engine, it is recommend that you replace\n        every print operation in the engine's handlers triggered every iteration with\n        ``pbar.log_message`` to guarantee the correct format of the stdout.\n\n    Note:\n        When using inside jupyter notebook, `ProgressBar` automatically uses `tqdm_notebook`. For correct rendering,\n        please install `ipywidgets <https://ipywidgets.readthedocs.io/en/stable/user_install.html#installation>`_.\n        Due to `tqdm notebook bugs <https://github.com/tqdm/tqdm/issues/594>`_, bar format may be needed to be set\n        to an empty string value.\n\n    \"\"\"\n\n    events_order = [\n        Events.STARTED,\n        Events.EPOCH_STARTED,\n        Events.ITERATION_STARTED,\n        Events.ITERATION_COMPLETED,\n        Events.EPOCH_COMPLETED,\n        Events.COMPLETED\n    ]\n\n    def __init__(self, persist=False,\n                 bar_format='{desc}[{n_fmt}/{total_fmt}] {percentage:3.0f}%|{bar}{postfix} [{elapsed}<{remaining}]',\n                 **tqdm_kwargs):\n\n        try:\n            from tqdm.autonotebook import tqdm\n        except ImportError:\n            raise RuntimeError(\"This contrib module requires tqdm to be installed. \"\n                               \"Please install it with command: \\n pip install tqdm\")\n\n        self.pbar_cls = tqdm\n        self.pbar = None\n        self.persist = persist\n        self.bar_format = bar_format\n        self.tqdm_kwargs = tqdm_kwargs\n\n    def _reset(self, pbar_total):\n        self.pbar = self.pbar_cls(\n            total=pbar_total,\n            leave=self.persist,\n            bar_format=self.bar_format,\n            **self.tqdm_kwargs\n        )\n\n    def _close(self, engine):\n        if self.pbar:\n            self.pbar.close()\n        self.pbar = None\n\n    @staticmethod\n    def _compare_lt(event1, event2):\n        i1 = ProgressBar.events_order.index(event1)\n        i2 = ProgressBar.events_order.index(event2)\n        return i1 < i2\n\n    @staticmethod\n    def log_message(message):\n        \"\"\"\n        Logs a message, preserving the progress bar correct output format.\n\n        Args:\n            message (str): string you wish to log.\n        \"\"\"\n        from tqdm import tqdm\n        tqdm.write(message)\n\n    def attach(self, engine, metric_names=None, output_transform=None,\n               event_name=Events.ITERATION_COMPLETED,\n               closing_event_name=Events.EPOCH_COMPLETED):\n        \"\"\"\n        Attaches the progress bar to an engine object.\n\n        Args:\n            engine (Engine): engine object.\n            metric_names (list, optional): list of the metrics names to log as the bar progresses\n            output_transform (callable, optional): a function to select what you want to print from the engine's\n                output. This function may return either a dictionary with entries in the format of ``{name: value}``,\n                or a single scalar, which will be displayed with the default name `output`.\n            event_name: event's name on which the progress bar advances. Valid events are from\n                :class:`~ignite.engine.Events`.\n            closing_event_name: event's name on which the progress bar is closed. Valid events are from\n                :class:`~ignite.engine.Events`.\n        \"\"\"\n        desc = self.tqdm_kwargs.get(\"desc\", \"Epoch\")\n\n        if not (event_name in Events and closing_event_name in Events):\n            raise ValueError(\"Logging and closing events should be only ignite.engine.Events\")\n\n        if not self._compare_lt(event_name, closing_event_name):\n            raise ValueError(\"Logging event {} should be called before closing event {}\"\n                             .format(event_name, closing_event_name))\n\n        log_handler = _OutputHandler(desc, metric_names, output_transform,\n                                     event_name=event_name,\n                                     closing_event_name=closing_event_name)\n        super(ProgressBar, self).attach(engine, log_handler, event_name)\n        engine.add_event_handler(closing_event_name, self._close)\n\n\nclass _OutputHandler(BaseOutputHandler):\n    \"\"\"Helper handler to log engine's output and/or metrics\n\n    Args:\n        description (str): progress bar description.\n        metric_names (list of str, optional): list of metric names to plot.\n        output_transform (callable, optional): output transform function to prepare `engine.state.output` as a number.\n            For example, `output_transform = lambda output: output`\n            This function can also return a dictionary, e.g `{'loss': loss1, `another_loss`: loss2}` to label the plot\n            with corresponding keys.\n        event_name: event's name on which the progress bar advances. Valid events are from\n            :class:`~ignite.engine.Events` or any `event_name` added by\n            :meth:`~ignite.engine.Engine.register_events`.\n        closing_event_name: event's name on which the progress bar is closed. Valid events are from\n            :class:`~ignite.engine.Events` or any `event_name` added by\n            :meth:`~ignite.engine.Engine.register_events`.\n\n    \"\"\"\n    def __init__(self, description, metric_names=None, output_transform=None,\n                 event_name=Events.ITERATION_COMPLETED,\n                 closing_event_name=Events.EPOCH_COMPLETED):\n        if metric_names is None and output_transform is None:\n            # This helps to avoid 'Either metric_names or output_transform should be defined' of BaseOutputHandler\n            metric_names = []\n        super(_OutputHandler, self).__init__(description, metric_names, output_transform, another_engine=None)\n        self.event_name = event_name\n        self.closing_event_name = closing_event_name\n\n    @staticmethod\n    def get_max_number_events(event_name, engine):\n        if event_name in (Events.ITERATION_STARTED, Events.ITERATION_COMPLETED):\n            return len(engine.state.dataloader)\n        if event_name in (Events.EPOCH_STARTED, Events.EPOCH_COMPLETED):\n            return engine.state.max_epochs\n        return 1\n\n    def __call__(self, engine, logger, event_name):\n\n        if logger.pbar is None:\n            logger._reset(pbar_total=self.get_max_number_events(self.event_name, engine))\n\n        desc = self.tag\n        max_num_of_closing_events = self.get_max_number_events(self.closing_event_name, engine)\n        if max_num_of_closing_events > 1:\n            global_step = engine.state.get_event_attrib_value(self.closing_event_name)\n            desc += \" [{}/{}]\".format(global_step, max_num_of_closing_events)\n        logger.pbar.set_description(desc)\n\n        metrics = self._setup_output_metrics(engine)\n\n        rendered_metrics = {}\n        for key, value in metrics.items():\n            if isinstance(value, numbers.Number) or \\\n                    isinstance(value, torch.Tensor) and value.ndimension() == 0:\n                rendered_metrics[key] = \"{:.2e}\".format(value)\n            elif isinstance(value, torch.Tensor) and value.ndimension() == 1:\n                for i, v in enumerate(value):\n                    k = \"{}_{}\".format(key, i)\n                    rendered_metrics[k] = \"{:.2e}\".format(v)\n            else:\n                warnings.warn(\"ProgressBar can not log \"\n                              \"metrics value type {}\".format(type(value)))\n\n        if rendered_metrics:\n            logger.pbar.set_postfix(**rendered_metrics)\n\n        logger.pbar.update()\n", "path": "ignite/contrib/handlers/tqdm_logger.py"}]}