We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Remove handler feature in Engine
I recently encountered the cases where I would like to remove a handler and optionally replace it with another one. The following code is used:
```python
def remove_handler(engine, handler, event_name):
    assert event_name in engine._event_handlers    
    engine._event_handlers[event_name] = [(h, args, kwargs) 
                                          for h, args, kwargs in engine._event_handlers[event_name] 
                                            if h != handler]
```

@alykhantejani @jasonkriss what do you guys think about inserting such method into `Engine` ?
cc @anmolsjoshi 

--- 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/engine/engine.py`
Content:
```
1 import inspect
2 import logging
3 import sys
4 import time
5 from collections import defaultdict
6 from enum import Enum
7 
8 from ignite._utils import _to_hours_mins_secs
9 
10 IS_PYTHON2 = sys.version_info[0] < 3
11 
12 
13 class Events(Enum):
14     """Events that are fired by the :class:`~ignite.engine.Engine` during execution."""
15     EPOCH_STARTED = "epoch_started"
16     EPOCH_COMPLETED = "epoch_completed"
17     STARTED = "started"
18     COMPLETED = "completed"
19     ITERATION_STARTED = "iteration_started"
20     ITERATION_COMPLETED = "iteration_completed"
21     EXCEPTION_RAISED = "exception_raised"
22 
23 
24 class State(object):
25     """An object that is used to pass internal and user-defined state between event handlers."""
26     def __init__(self, **kwargs):
27         self.iteration = 0
28         self.output = None
29         self.batch = None
30         for k, v in kwargs.items():
31             setattr(self, k, v)
32 
33 
34 class Engine(object):
35     """Runs a given process_function over each batch of a dataset, emitting events as it goes.
36 
37     Args:
38         process_function (callable): A function receiving a handle to the engine and the current batch
39             in each iteration, and returns data to be stored in the engine's state.
40 
41     Example usage:
42 
43     .. code-block:: python
44 
45         def train_and_store_loss(engine, batch):
46             inputs, targets = batch
47             optimizer.zero_grad()
48             outputs = model(inputs)
49             loss = loss_fn(outputs, targets)
50             loss.backward()
51             optimizer.step()
52             return loss.item()
53 
54         engine = Engine(train_and_store_loss)
55         engine.run(data_loader)
56 
57         # Loss value is now stored in `engine.state.output`.
58 
59     """
60     def __init__(self, process_function):
61         self._event_handlers = defaultdict(list)
62         self._logger = logging.getLogger(__name__ + "." + self.__class__.__name__)
63         self._logger.addHandler(logging.NullHandler())
64         self._process_function = process_function
65         self.should_terminate = False
66         self.should_terminate_single_epoch = False
67         self.state = None
68         self._allowed_events = []
69 
70         self.register_events(*Events)
71 
72         if self._process_function is None:
73             raise ValueError("Engine must be given a processing function in order to run.")
74 
75         self._check_signature(process_function, 'process_function', None)
76 
77     def register_events(self, *event_names):
78         """Add events that can be fired.
79 
80         Registering an event will let the user fire these events at any point.
81         This opens the door to make the :meth:`~ignite.engine.Engine.run` loop even more
82         configurable.
83 
84         By default, the events from :class:`~ignite.engine.Events` are registerd.
85 
86         Args:
87             *event_names: An object (ideally a string or int) to define the
88                 name of the event being supported.
89 
90         Example usage:
91 
92         .. code-block:: python
93 
94             from enum import Enum
95 
96             class Custom_Events(Enum):
97                 FOO_EVENT = "foo_event"
98                 BAR_EVENT = "bar_event"
99 
100             engine = Engine(process_function)
101             engine.register_events(*Custom_Events)
102 
103         """
104         for name in event_names:
105             self._allowed_events.append(name)
106 
107     def add_event_handler(self, event_name, handler, *args, **kwargs):
108         """Add an event handler to be executed when the specified event is fired.
109 
110         Args:
111             event_name: An event to attach the handler to. Valid events are from :class:`~ignite.engine.Events`
112                 or any `event_name` added by :meth:`~ignite.engine.Engine.register_events`.
113             handler (callable): the callable event handler that should be invoked
114             *args: optional args to be passed to `handler`.
115             **kwargs: optional keyword args to be passed to `handler`.
116 
117         Notes:
118               The handler function's first argument will be `self`, the :class:`~ignite.engine.Engine` object it
119               was bound to.
120 
121               Note that other arguments can be passed to the handler in addition to the `*args` and  `**kwargs`
122               passed here, for example during :attr:`~ignite.engine.Events.EXCEPTION_RAISED`.
123 
124         Example usage:
125 
126         .. code-block:: python
127 
128             engine = Engine(process_function)
129 
130             def print_epoch(engine):
131                 print("Epoch: {}".format(engine.state.epoch))
132 
133             engine.add_event_handler(Events.EPOCH_COMPLETED, print_epoch)
134 
135         """
136         if event_name not in self._allowed_events:
137             self._logger.error("attempt to add event handler to an invalid event %s.", event_name)
138             raise ValueError("Event {} is not a valid event for this Engine.".format(event_name))
139 
140         event_args = (Exception(), ) if event_name == Events.EXCEPTION_RAISED else ()
141         self._check_signature(handler, 'handler', *(event_args + args), **kwargs)
142 
143         self._event_handlers[event_name].append((handler, args, kwargs))
144         self._logger.debug("added handler for event %s.", event_name)
145 
146     def has_event_handler(self, handler, event_name=None):
147         """Check if the specified event has the specified handler.
148 
149         Args:
150             handler (callable): the callable event handler.
151             event_name: The event the handler attached to. Set this
152                 to ``None`` to search all events.
153         """
154         if event_name is not None:
155             if event_name not in self._event_handlers:
156                 return False
157             events = [event_name]
158         else:
159             events = self._event_handlers
160         for e in events:
161             for h, _, _ in self._event_handlers[e]:
162                 if h == handler:
163                     return True
164         return False
165 
166     def _check_signature(self, fn, fn_description, *args, **kwargs):
167         exception_msg = None
168 
169         if IS_PYTHON2:
170             try:
171                 callable_ = fn if hasattr(fn, '__name__') else fn.__call__
172                 inspect.getcallargs(callable_, self, *args, **kwargs)
173             except TypeError as exc:
174                 spec = inspect.getargspec(callable_)
175                 fn_params = list(spec.args)
176                 exception_msg = str(exc)
177         else:
178             signature = inspect.signature(fn)
179             try:
180                 signature.bind(self, *args, **kwargs)
181             except TypeError as exc:
182                 fn_params = list(signature.parameters)
183                 exception_msg = str(exc)
184 
185         if exception_msg:
186             passed_params = [self] + list(args) + list(kwargs)
187             raise ValueError("Error adding {} '{}': "
188                              "takes parameters {} but will be called with {} "
189                              "({}).".format(
190                                  fn, fn_description, fn_params, passed_params, exception_msg))
191 
192     def on(self, event_name, *args, **kwargs):
193         """Decorator shortcut for add_event_handler.
194 
195         Args:
196             event_name: An event to attach the handler to. Valid events are from :class:`~ignite.engine.Events` or
197                 any `event_name` added by :meth:`~ignite.engine.Engine.register_events`.
198             *args: optional args to be passed to `handler`.
199             **kwargs: optional keyword args to be passed to `handler`.
200 
201         """
202         def decorator(f):
203             self.add_event_handler(event_name, f, *args, **kwargs)
204             return f
205         return decorator
206 
207     def _fire_event(self, event_name, *event_args, **event_kwargs):
208         """Execute all the handlers associated with given event.
209 
210         This method executes all handlers associated with the event
211         `event_name`. Optional positional and keyword arguments can be used to
212         pass arguments to **all** handlers added with this event. These
213         aguments updates arguments passed using :meth:`~ignite.engine.Engine.add_event_handler`.
214 
215         Args:
216             event_name: event for which the handlers should be executed. Valid
217                 events are from :class:`~ignite.engine.Events` or any `event_name` added by
218                 :meth:`~ignite.engine.Engine.register_events`.
219             *event_args: optional args to be passed to all handlers.
220             **event_kwargs: optional keyword args to be passed to all handlers.
221 
222         """
223         if event_name in self._allowed_events:
224             self._logger.debug("firing handlers for event %s ", event_name)
225             for func, args, kwargs in self._event_handlers[event_name]:
226                 kwargs.update(event_kwargs)
227                 func(self, *(event_args + args), **kwargs)
228 
229     def fire_event(self, event_name):
230         """Execute all the handlers associated with given event.
231 
232         This method executes all handlers associated with the event
233         `event_name`. This is the method used in :meth:`~ignite.engine.Engine.run` to call the
234         core events found in :class:`~ignite.engine.Events`.
235 
236         Custom events can be fired if they have been registered before with
237         :meth:`~ignite.engine.Engine.register_events`. The engine `state` attribute should be used
238         to exchange "dynamic" data among `process_function` and handlers.
239 
240         This method is called automatically for core events. If no custom
241         events are used in the engine, there is no need for the user to call
242         the method.
243 
244         Args:
245             event_name: event for which the handlers should be executed. Valid
246                 events are from :class:`~ignite.engine.Events` or any `event_name` added by
247                 :meth:`~ignite.engine.Engine.register_events`.
248 
249         """
250         return self._fire_event(event_name)
251 
252     def terminate(self):
253         """Sends terminate signal to the engine, so that it terminates completely the run after the current iteration.
254         """
255         self._logger.info("Terminate signaled. Engine will stop after current iteration is finished.")
256         self.should_terminate = True
257 
258     def terminate_epoch(self):
259         """Sends terminate signal to the engine, so that it terminates the current epoch after the current iteration.
260         """
261         self._logger.info("Terminate current epoch is signaled. "
262                           "Current epoch iteration will stop after current iteration is finished.")
263         self.should_terminate_single_epoch = True
264 
265     def _run_once_on_dataset(self):
266         start_time = time.time()
267 
268         try:
269             for batch in self.state.dataloader:
270                 self.state.batch = batch
271                 self.state.iteration += 1
272                 self._fire_event(Events.ITERATION_STARTED)
273                 self.state.output = self._process_function(self, batch)
274                 self._fire_event(Events.ITERATION_COMPLETED)
275                 if self.should_terminate or self.should_terminate_single_epoch:
276                     self.should_terminate_single_epoch = False
277                     break
278 
279         except BaseException as e:
280             self._logger.error("Current run is terminating due to exception: %s.", str(e))
281             self._handle_exception(e)
282 
283         time_taken = time.time() - start_time
284         hours, mins, secs = _to_hours_mins_secs(time_taken)
285 
286         return hours, mins, secs
287 
288     def _handle_exception(self, e):
289         if Events.EXCEPTION_RAISED in self._event_handlers:
290             self._fire_event(Events.EXCEPTION_RAISED, e)
291         else:
292             raise e
293 
294     def run(self, data, max_epochs=1):
295         """Runs the process_function over the passed data.
296 
297         Args:
298             data (Iterable): Collection of batches allowing repeated iteration (e.g., list or `DataLoader`).
299             max_epochs (int, optional): max epochs to run for (default: 1).
300 
301         Returns:
302             State: output state.
303         """
304 
305         self.state = State(dataloader=data, epoch=0, max_epochs=max_epochs, metrics={})
306 
307         try:
308             self._logger.info("Engine run starting with max_epochs={}.".format(max_epochs))
309             start_time = time.time()
310             self._fire_event(Events.STARTED)
311             while self.state.epoch < max_epochs and not self.should_terminate:
312                 self.state.epoch += 1
313                 self._fire_event(Events.EPOCH_STARTED)
314                 hours, mins, secs = self._run_once_on_dataset()
315                 self._logger.info("Epoch[%s] Complete. Time taken: %02d:%02d:%02d", self.state.epoch, hours, mins, secs)
316                 if self.should_terminate:
317                     break
318                 self._fire_event(Events.EPOCH_COMPLETED)
319 
320             self._fire_event(Events.COMPLETED)
321             time_taken = time.time() - start_time
322             hours, mins, secs = _to_hours_mins_secs(time_taken)
323             self._logger.info("Engine run complete. Time taken %02d:%02d:%02d" % (hours, mins, secs))
324 
325         except BaseException as e:
326             self._logger.error("Engine run is terminating due to exception: %s.", str(e))
327             self._handle_exception(e)
328 
329         return self.state
330
```
--- 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/engine/engine.py b/ignite/engine/engine.py
--- a/ignite/engine/engine.py
+++ b/ignite/engine/engine.py
@@ -163,6 +163,23 @@
                     return True
         return False
 
+    def remove_event_handler(self, handler, event_name):
+        """Remove event handler `handler` from registered handlers of the engine
+
+        Args:
+            handler (callable): the callable event handler that should be removed
+            event_name: The event the handler attached to.
+
+        """
+        if event_name not in self._event_handlers:
+            raise ValueError("Input event name '{}' does not exist".format(event_name))
+
+        new_event_handlers = [(h, args, kwargs) for h, args, kwargs in self._event_handlers[event_name]
+                              if h != handler]
+        if len(new_event_handlers) == len(self._event_handlers[event_name]):
+            raise ValueError("Input handler '{}' is not found among registered event handlers".format(handler))
+        self._event_handlers[event_name] = new_event_handlers
+
     def _check_signature(self, fn, fn_description, *args, **kwargs):
         exception_msg = None

{"golden_diff": "diff --git a/ignite/engine/engine.py b/ignite/engine/engine.py\n--- a/ignite/engine/engine.py\n+++ b/ignite/engine/engine.py\n@@ -163,6 +163,23 @@\n                     return True\n         return False\n \n+    def remove_event_handler(self, handler, event_name):\n+        \"\"\"Remove event handler `handler` from registered handlers of the engine\n+\n+        Args:\n+            handler (callable): the callable event handler that should be removed\n+            event_name: The event the handler attached to.\n+\n+        \"\"\"\n+        if event_name not in self._event_handlers:\n+            raise ValueError(\"Input event name '{}' does not exist\".format(event_name))\n+\n+        new_event_handlers = [(h, args, kwargs) for h, args, kwargs in self._event_handlers[event_name]\n+                              if h != handler]\n+        if len(new_event_handlers) == len(self._event_handlers[event_name]):\n+            raise ValueError(\"Input handler '{}' is not found among registered event handlers\".format(handler))\n+        self._event_handlers[event_name] = new_event_handlers\n+\n     def _check_signature(self, fn, fn_description, *args, **kwargs):\n         exception_msg = None\n", "issue": "Remove handler feature in Engine\nI recently encountered the cases where I would like to remove a handler and optionally replace it with another one. The following code is used:\r\n```python\r\ndef remove_handler(engine, handler, event_name):\r\n    assert event_name in engine._event_handlers    \r\n    engine._event_handlers[event_name] = [(h, args, kwargs) \r\n                                          for h, args, kwargs in engine._event_handlers[event_name] \r\n                                            if h != handler]\r\n```\r\n\r\n@alykhantejani @jasonkriss what do you guys think about inserting such method into `Engine` ?\r\ncc @anmolsjoshi \n", "before_files": [{"content": "import inspect\nimport logging\nimport sys\nimport time\nfrom collections import defaultdict\nfrom enum import Enum\n\nfrom ignite._utils import _to_hours_mins_secs\n\nIS_PYTHON2 = sys.version_info[0] < 3\n\n\nclass Events(Enum):\n    \"\"\"Events that are fired by the :class:`~ignite.engine.Engine` during execution.\"\"\"\n    EPOCH_STARTED = \"epoch_started\"\n    EPOCH_COMPLETED = \"epoch_completed\"\n    STARTED = \"started\"\n    COMPLETED = \"completed\"\n    ITERATION_STARTED = \"iteration_started\"\n    ITERATION_COMPLETED = \"iteration_completed\"\n    EXCEPTION_RAISED = \"exception_raised\"\n\n\nclass State(object):\n    \"\"\"An object that is used to pass internal and user-defined state between event handlers.\"\"\"\n    def __init__(self, **kwargs):\n        self.iteration = 0\n        self.output = None\n        self.batch = None\n        for k, v in kwargs.items():\n            setattr(self, k, v)\n\n\nclass Engine(object):\n    \"\"\"Runs a given process_function over each batch of a dataset, emitting events as it goes.\n\n    Args:\n        process_function (callable): A function receiving a handle to the engine and the current batch\n            in each iteration, and returns data to be stored in the engine's state.\n\n    Example usage:\n\n    .. code-block:: python\n\n        def train_and_store_loss(engine, batch):\n            inputs, targets = batch\n            optimizer.zero_grad()\n            outputs = model(inputs)\n            loss = loss_fn(outputs, targets)\n            loss.backward()\n            optimizer.step()\n            return loss.item()\n\n        engine = Engine(train_and_store_loss)\n        engine.run(data_loader)\n\n        # Loss value is now stored in `engine.state.output`.\n\n    \"\"\"\n    def __init__(self, process_function):\n        self._event_handlers = defaultdict(list)\n        self._logger = logging.getLogger(__name__ + \".\" + self.__class__.__name__)\n        self._logger.addHandler(logging.NullHandler())\n        self._process_function = process_function\n        self.should_terminate = False\n        self.should_terminate_single_epoch = False\n        self.state = None\n        self._allowed_events = []\n\n        self.register_events(*Events)\n\n        if self._process_function is None:\n            raise ValueError(\"Engine must be given a processing function in order to run.\")\n\n        self._check_signature(process_function, 'process_function', None)\n\n    def register_events(self, *event_names):\n        \"\"\"Add events that can be fired.\n\n        Registering an event will let the user fire these events at any point.\n        This opens the door to make the :meth:`~ignite.engine.Engine.run` loop even more\n        configurable.\n\n        By default, the events from :class:`~ignite.engine.Events` are registerd.\n\n        Args:\n            *event_names: An object (ideally a string or int) to define the\n                name of the event being supported.\n\n        Example usage:\n\n        .. code-block:: python\n\n            from enum import Enum\n\n            class Custom_Events(Enum):\n                FOO_EVENT = \"foo_event\"\n                BAR_EVENT = \"bar_event\"\n\n            engine = Engine(process_function)\n            engine.register_events(*Custom_Events)\n\n        \"\"\"\n        for name in event_names:\n            self._allowed_events.append(name)\n\n    def add_event_handler(self, event_name, handler, *args, **kwargs):\n        \"\"\"Add an event handler to be executed when the specified event is fired.\n\n        Args:\n            event_name: An event to attach the handler to. Valid events are from :class:`~ignite.engine.Events`\n                or any `event_name` added by :meth:`~ignite.engine.Engine.register_events`.\n            handler (callable): the callable event handler that should be invoked\n            *args: optional args to be passed to `handler`.\n            **kwargs: optional keyword args to be passed to `handler`.\n\n        Notes:\n              The handler function's first argument will be `self`, the :class:`~ignite.engine.Engine` object it\n              was bound to.\n\n              Note that other arguments can be passed to the handler in addition to the `*args` and  `**kwargs`\n              passed here, for example during :attr:`~ignite.engine.Events.EXCEPTION_RAISED`.\n\n        Example usage:\n\n        .. code-block:: python\n\n            engine = Engine(process_function)\n\n            def print_epoch(engine):\n                print(\"Epoch: {}\".format(engine.state.epoch))\n\n            engine.add_event_handler(Events.EPOCH_COMPLETED, print_epoch)\n\n        \"\"\"\n        if event_name not in self._allowed_events:\n            self._logger.error(\"attempt to add event handler to an invalid event %s.\", event_name)\n            raise ValueError(\"Event {} is not a valid event for this Engine.\".format(event_name))\n\n        event_args = (Exception(), ) if event_name == Events.EXCEPTION_RAISED else ()\n        self._check_signature(handler, 'handler', *(event_args + args), **kwargs)\n\n        self._event_handlers[event_name].append((handler, args, kwargs))\n        self._logger.debug(\"added handler for event %s.\", event_name)\n\n    def has_event_handler(self, handler, event_name=None):\n        \"\"\"Check if the specified event has the specified handler.\n\n        Args:\n            handler (callable): the callable event handler.\n            event_name: The event the handler attached to. Set this\n                to ``None`` to search all events.\n        \"\"\"\n        if event_name is not None:\n            if event_name not in self._event_handlers:\n                return False\n            events = [event_name]\n        else:\n            events = self._event_handlers\n        for e in events:\n            for h, _, _ in self._event_handlers[e]:\n                if h == handler:\n                    return True\n        return False\n\n    def _check_signature(self, fn, fn_description, *args, **kwargs):\n        exception_msg = None\n\n        if IS_PYTHON2:\n            try:\n                callable_ = fn if hasattr(fn, '__name__') else fn.__call__\n                inspect.getcallargs(callable_, self, *args, **kwargs)\n            except TypeError as exc:\n                spec = inspect.getargspec(callable_)\n                fn_params = list(spec.args)\n                exception_msg = str(exc)\n        else:\n            signature = inspect.signature(fn)\n            try:\n                signature.bind(self, *args, **kwargs)\n            except TypeError as exc:\n                fn_params = list(signature.parameters)\n                exception_msg = str(exc)\n\n        if exception_msg:\n            passed_params = [self] + list(args) + list(kwargs)\n            raise ValueError(\"Error adding {} '{}': \"\n                             \"takes parameters {} but will be called with {} \"\n                             \"({}).\".format(\n                                 fn, fn_description, fn_params, passed_params, exception_msg))\n\n    def on(self, event_name, *args, **kwargs):\n        \"\"\"Decorator shortcut for add_event_handler.\n\n        Args:\n            event_name: An event to attach the handler to. Valid events are from :class:`~ignite.engine.Events` or\n                any `event_name` added by :meth:`~ignite.engine.Engine.register_events`.\n            *args: optional args to be passed to `handler`.\n            **kwargs: optional keyword args to be passed to `handler`.\n\n        \"\"\"\n        def decorator(f):\n            self.add_event_handler(event_name, f, *args, **kwargs)\n            return f\n        return decorator\n\n    def _fire_event(self, event_name, *event_args, **event_kwargs):\n        \"\"\"Execute all the handlers associated with given event.\n\n        This method executes all handlers associated with the event\n        `event_name`. Optional positional and keyword arguments can be used to\n        pass arguments to **all** handlers added with this event. These\n        aguments updates arguments passed using :meth:`~ignite.engine.Engine.add_event_handler`.\n\n        Args:\n            event_name: event for which the handlers should be executed. Valid\n                events are from :class:`~ignite.engine.Events` or any `event_name` added by\n                :meth:`~ignite.engine.Engine.register_events`.\n            *event_args: optional args to be passed to all handlers.\n            **event_kwargs: optional keyword args to be passed to all handlers.\n\n        \"\"\"\n        if event_name in self._allowed_events:\n            self._logger.debug(\"firing handlers for event %s \", event_name)\n            for func, args, kwargs in self._event_handlers[event_name]:\n                kwargs.update(event_kwargs)\n                func(self, *(event_args + args), **kwargs)\n\n    def fire_event(self, event_name):\n        \"\"\"Execute all the handlers associated with given event.\n\n        This method executes all handlers associated with the event\n        `event_name`. This is the method used in :meth:`~ignite.engine.Engine.run` to call the\n        core events found in :class:`~ignite.engine.Events`.\n\n        Custom events can be fired if they have been registered before with\n        :meth:`~ignite.engine.Engine.register_events`. The engine `state` attribute should be used\n        to exchange \"dynamic\" data among `process_function` and handlers.\n\n        This method is called automatically for core events. If no custom\n        events are used in the engine, there is no need for the user to call\n        the method.\n\n        Args:\n            event_name: event for which the handlers should be executed. Valid\n                events are from :class:`~ignite.engine.Events` or any `event_name` added by\n                :meth:`~ignite.engine.Engine.register_events`.\n\n        \"\"\"\n        return self._fire_event(event_name)\n\n    def terminate(self):\n        \"\"\"Sends terminate signal to the engine, so that it terminates completely the run after the current iteration.\n        \"\"\"\n        self._logger.info(\"Terminate signaled. Engine will stop after current iteration is finished.\")\n        self.should_terminate = True\n\n    def terminate_epoch(self):\n        \"\"\"Sends terminate signal to the engine, so that it terminates the current epoch after the current iteration.\n        \"\"\"\n        self._logger.info(\"Terminate current epoch is signaled. \"\n                          \"Current epoch iteration will stop after current iteration is finished.\")\n        self.should_terminate_single_epoch = True\n\n    def _run_once_on_dataset(self):\n        start_time = time.time()\n\n        try:\n            for batch in self.state.dataloader:\n                self.state.batch = batch\n                self.state.iteration += 1\n                self._fire_event(Events.ITERATION_STARTED)\n                self.state.output = self._process_function(self, batch)\n                self._fire_event(Events.ITERATION_COMPLETED)\n                if self.should_terminate or self.should_terminate_single_epoch:\n                    self.should_terminate_single_epoch = False\n                    break\n\n        except BaseException as e:\n            self._logger.error(\"Current run is terminating due to exception: %s.\", str(e))\n            self._handle_exception(e)\n\n        time_taken = time.time() - start_time\n        hours, mins, secs = _to_hours_mins_secs(time_taken)\n\n        return hours, mins, secs\n\n    def _handle_exception(self, e):\n        if Events.EXCEPTION_RAISED in self._event_handlers:\n            self._fire_event(Events.EXCEPTION_RAISED, e)\n        else:\n            raise e\n\n    def run(self, data, max_epochs=1):\n        \"\"\"Runs the process_function over the passed data.\n\n        Args:\n            data (Iterable): Collection of batches allowing repeated iteration (e.g., list or `DataLoader`).\n            max_epochs (int, optional): max epochs to run for (default: 1).\n\n        Returns:\n            State: output state.\n        \"\"\"\n\n        self.state = State(dataloader=data, epoch=0, max_epochs=max_epochs, metrics={})\n\n        try:\n            self._logger.info(\"Engine run starting with max_epochs={}.\".format(max_epochs))\n            start_time = time.time()\n            self._fire_event(Events.STARTED)\n            while self.state.epoch < max_epochs and not self.should_terminate:\n                self.state.epoch += 1\n                self._fire_event(Events.EPOCH_STARTED)\n                hours, mins, secs = self._run_once_on_dataset()\n                self._logger.info(\"Epoch[%s] Complete. Time taken: %02d:%02d:%02d\", self.state.epoch, hours, mins, secs)\n                if self.should_terminate:\n                    break\n                self._fire_event(Events.EPOCH_COMPLETED)\n\n            self._fire_event(Events.COMPLETED)\n            time_taken = time.time() - start_time\n            hours, mins, secs = _to_hours_mins_secs(time_taken)\n            self._logger.info(\"Engine run complete. Time taken %02d:%02d:%02d\" % (hours, mins, secs))\n\n        except BaseException as e:\n            self._logger.error(\"Engine run is terminating due to exception: %s.\", str(e))\n            self._handle_exception(e)\n\n        return self.state\n", "path": "ignite/engine/engine.py"}], "after_files": [{"content": "import inspect\nimport logging\nimport sys\nimport time\nfrom collections import defaultdict\nfrom enum import Enum\n\nfrom ignite._utils import _to_hours_mins_secs\n\nIS_PYTHON2 = sys.version_info[0] < 3\n\n\nclass Events(Enum):\n    \"\"\"Events that are fired by the :class:`~ignite.engine.Engine` during execution.\"\"\"\n    EPOCH_STARTED = \"epoch_started\"\n    EPOCH_COMPLETED = \"epoch_completed\"\n    STARTED = \"started\"\n    COMPLETED = \"completed\"\n    ITERATION_STARTED = \"iteration_started\"\n    ITERATION_COMPLETED = \"iteration_completed\"\n    EXCEPTION_RAISED = \"exception_raised\"\n\n\nclass State(object):\n    \"\"\"An object that is used to pass internal and user-defined state between event handlers.\"\"\"\n    def __init__(self, **kwargs):\n        self.iteration = 0\n        self.output = None\n        self.batch = None\n        for k, v in kwargs.items():\n            setattr(self, k, v)\n\n\nclass Engine(object):\n    \"\"\"Runs a given process_function over each batch of a dataset, emitting events as it goes.\n\n    Args:\n        process_function (callable): A function receiving a handle to the engine and the current batch\n            in each iteration, and returns data to be stored in the engine's state.\n\n    Example usage:\n\n    .. code-block:: python\n\n        def train_and_store_loss(engine, batch):\n            inputs, targets = batch\n            optimizer.zero_grad()\n            outputs = model(inputs)\n            loss = loss_fn(outputs, targets)\n            loss.backward()\n            optimizer.step()\n            return loss.item()\n\n        engine = Engine(train_and_store_loss)\n        engine.run(data_loader)\n\n        # Loss value is now stored in `engine.state.output`.\n\n    \"\"\"\n    def __init__(self, process_function):\n        self._event_handlers = defaultdict(list)\n        self._logger = logging.getLogger(__name__ + \".\" + self.__class__.__name__)\n        self._logger.addHandler(logging.NullHandler())\n        self._process_function = process_function\n        self.should_terminate = False\n        self.should_terminate_single_epoch = False\n        self.state = None\n        self._allowed_events = []\n\n        self.register_events(*Events)\n\n        if self._process_function is None:\n            raise ValueError(\"Engine must be given a processing function in order to run.\")\n\n        self._check_signature(process_function, 'process_function', None)\n\n    def register_events(self, *event_names):\n        \"\"\"Add events that can be fired.\n\n        Registering an event will let the user fire these events at any point.\n        This opens the door to make the :meth:`~ignite.engine.Engine.run` loop even more\n        configurable.\n\n        By default, the events from :class:`~ignite.engine.Events` are registerd.\n\n        Args:\n            *event_names: An object (ideally a string or int) to define the\n                name of the event being supported.\n\n        Example usage:\n\n        .. code-block:: python\n\n            from enum import Enum\n\n            class Custom_Events(Enum):\n                FOO_EVENT = \"foo_event\"\n                BAR_EVENT = \"bar_event\"\n\n            engine = Engine(process_function)\n            engine.register_events(*Custom_Events)\n\n        \"\"\"\n        for name in event_names:\n            self._allowed_events.append(name)\n\n    def add_event_handler(self, event_name, handler, *args, **kwargs):\n        \"\"\"Add an event handler to be executed when the specified event is fired.\n\n        Args:\n            event_name: An event to attach the handler to. Valid events are from :class:`~ignite.engine.Events`\n                or any `event_name` added by :meth:`~ignite.engine.Engine.register_events`.\n            handler (callable): the callable event handler that should be invoked\n            *args: optional args to be passed to `handler`.\n            **kwargs: optional keyword args to be passed to `handler`.\n\n        Notes:\n              The handler function's first argument will be `self`, the :class:`~ignite.engine.Engine` object it\n              was bound to.\n\n              Note that other arguments can be passed to the handler in addition to the `*args` and  `**kwargs`\n              passed here, for example during :attr:`~ignite.engine.Events.EXCEPTION_RAISED`.\n\n        Example usage:\n\n        .. code-block:: python\n\n            engine = Engine(process_function)\n\n            def print_epoch(engine):\n                print(\"Epoch: {}\".format(engine.state.epoch))\n\n            engine.add_event_handler(Events.EPOCH_COMPLETED, print_epoch)\n\n        \"\"\"\n        if event_name not in self._allowed_events:\n            self._logger.error(\"attempt to add event handler to an invalid event %s.\", event_name)\n            raise ValueError(\"Event {} is not a valid event for this Engine.\".format(event_name))\n\n        event_args = (Exception(), ) if event_name == Events.EXCEPTION_RAISED else ()\n        self._check_signature(handler, 'handler', *(event_args + args), **kwargs)\n\n        self._event_handlers[event_name].append((handler, args, kwargs))\n        self._logger.debug(\"added handler for event %s.\", event_name)\n\n    def has_event_handler(self, handler, event_name=None):\n        \"\"\"Check if the specified event has the specified handler.\n\n        Args:\n            handler (callable): the callable event handler.\n            event_name: The event the handler attached to. Set this\n                to ``None`` to search all events.\n        \"\"\"\n        if event_name is not None:\n            if event_name not in self._event_handlers:\n                return False\n            events = [event_name]\n        else:\n            events = self._event_handlers\n        for e in events:\n            for h, _, _ in self._event_handlers[e]:\n                if h == handler:\n                    return True\n        return False\n\n    def remove_event_handler(self, handler, event_name):\n        \"\"\"Remove event handler `handler` from registered handlers of the engine\n\n        Args:\n            handler (callable): the callable event handler that should be removed\n            event_name: The event the handler attached to.\n\n        \"\"\"\n        if event_name not in self._event_handlers:\n            raise ValueError(\"Input event name '{}' does not exist\".format(event_name))\n\n        new_event_handlers = [(h, args, kwargs) for h, args, kwargs in self._event_handlers[event_name]\n                              if h != handler]\n        if len(new_event_handlers) == len(self._event_handlers[event_name]):\n            raise ValueError(\"Input handler '{}' is not found among registered event handlers\".format(handler))\n        self._event_handlers[event_name] = new_event_handlers\n\n    def _check_signature(self, fn, fn_description, *args, **kwargs):\n        exception_msg = None\n\n        if IS_PYTHON2:\n            try:\n                callable_ = fn if hasattr(fn, '__name__') else fn.__call__\n                inspect.getcallargs(callable_, self, *args, **kwargs)\n            except TypeError as exc:\n                spec = inspect.getargspec(callable_)\n                fn_params = list(spec.args)\n                exception_msg = str(exc)\n        else:\n            signature = inspect.signature(fn)\n            try:\n                signature.bind(self, *args, **kwargs)\n            except TypeError as exc:\n                fn_params = list(signature.parameters)\n                exception_msg = str(exc)\n\n        if exception_msg:\n            passed_params = [self] + list(args) + list(kwargs)\n            raise ValueError(\"Error adding {} '{}': \"\n                             \"takes parameters {} but will be called with {} \"\n                             \"({}).\".format(\n                                 fn, fn_description, fn_params, passed_params, exception_msg))\n\n    def on(self, event_name, *args, **kwargs):\n        \"\"\"Decorator shortcut for add_event_handler.\n\n        Args:\n            event_name: An event to attach the handler to. Valid events are from :class:`~ignite.engine.Events` or\n                any `event_name` added by :meth:`~ignite.engine.Engine.register_events`.\n            *args: optional args to be passed to `handler`.\n            **kwargs: optional keyword args to be passed to `handler`.\n\n        \"\"\"\n        def decorator(f):\n            self.add_event_handler(event_name, f, *args, **kwargs)\n            return f\n        return decorator\n\n    def _fire_event(self, event_name, *event_args, **event_kwargs):\n        \"\"\"Execute all the handlers associated with given event.\n\n        This method executes all handlers associated with the event\n        `event_name`. Optional positional and keyword arguments can be used to\n        pass arguments to **all** handlers added with this event. These\n        aguments updates arguments passed using :meth:`~ignite.engine.Engine.add_event_handler`.\n\n        Args:\n            event_name: event for which the handlers should be executed. Valid\n                events are from :class:`~ignite.engine.Events` or any `event_name` added by\n                :meth:`~ignite.engine.Engine.register_events`.\n            *event_args: optional args to be passed to all handlers.\n            **event_kwargs: optional keyword args to be passed to all handlers.\n\n        \"\"\"\n        if event_name in self._allowed_events:\n            self._logger.debug(\"firing handlers for event %s \", event_name)\n            for func, args, kwargs in self._event_handlers[event_name]:\n                kwargs.update(event_kwargs)\n                func(self, *(event_args + args), **kwargs)\n\n    def fire_event(self, event_name):\n        \"\"\"Execute all the handlers associated with given event.\n\n        This method executes all handlers associated with the event\n        `event_name`. This is the method used in :meth:`~ignite.engine.Engine.run` to call the\n        core events found in :class:`~ignite.engine.Events`.\n\n        Custom events can be fired if they have been registered before with\n        :meth:`~ignite.engine.Engine.register_events`. The engine `state` attribute should be used\n        to exchange \"dynamic\" data among `process_function` and handlers.\n\n        This method is called automatically for core events. If no custom\n        events are used in the engine, there is no need for the user to call\n        the method.\n\n        Args:\n            event_name: event for which the handlers should be executed. Valid\n                events are from :class:`~ignite.engine.Events` or any `event_name` added by\n                :meth:`~ignite.engine.Engine.register_events`.\n\n        \"\"\"\n        return self._fire_event(event_name)\n\n    def terminate(self):\n        \"\"\"Sends terminate signal to the engine, so that it terminates completely the run after the current iteration.\n        \"\"\"\n        self._logger.info(\"Terminate signaled. Engine will stop after current iteration is finished.\")\n        self.should_terminate = True\n\n    def terminate_epoch(self):\n        \"\"\"Sends terminate signal to the engine, so that it terminates the current epoch after the current iteration.\n        \"\"\"\n        self._logger.info(\"Terminate current epoch is signaled. \"\n                          \"Current epoch iteration will stop after current iteration is finished.\")\n        self.should_terminate_single_epoch = True\n\n    def _run_once_on_dataset(self):\n        start_time = time.time()\n\n        try:\n            for batch in self.state.dataloader:\n                self.state.batch = batch\n                self.state.iteration += 1\n                self._fire_event(Events.ITERATION_STARTED)\n                self.state.output = self._process_function(self, batch)\n                self._fire_event(Events.ITERATION_COMPLETED)\n                if self.should_terminate or self.should_terminate_single_epoch:\n                    self.should_terminate_single_epoch = False\n                    break\n\n        except BaseException as e:\n            self._logger.error(\"Current run is terminating due to exception: %s.\", str(e))\n            self._handle_exception(e)\n\n        time_taken = time.time() - start_time\n        hours, mins, secs = _to_hours_mins_secs(time_taken)\n\n        return hours, mins, secs\n\n    def _handle_exception(self, e):\n        if Events.EXCEPTION_RAISED in self._event_handlers:\n            self._fire_event(Events.EXCEPTION_RAISED, e)\n        else:\n            raise e\n\n    def run(self, data, max_epochs=1):\n        \"\"\"Runs the process_function over the passed data.\n\n        Args:\n            data (Iterable): Collection of batches allowing repeated iteration (e.g., list or `DataLoader`).\n            max_epochs (int, optional): max epochs to run for (default: 1).\n\n        Returns:\n            State: output state.\n        \"\"\"\n\n        self.state = State(dataloader=data, epoch=0, max_epochs=max_epochs, metrics={})\n\n        try:\n            self._logger.info(\"Engine run starting with max_epochs={}.\".format(max_epochs))\n            start_time = time.time()\n            self._fire_event(Events.STARTED)\n            while self.state.epoch < max_epochs and not self.should_terminate:\n                self.state.epoch += 1\n                self._fire_event(Events.EPOCH_STARTED)\n                hours, mins, secs = self._run_once_on_dataset()\n                self._logger.info(\"Epoch[%s] Complete. Time taken: %02d:%02d:%02d\", self.state.epoch, hours, mins, secs)\n                if self.should_terminate:\n                    break\n                self._fire_event(Events.EPOCH_COMPLETED)\n\n            self._fire_event(Events.COMPLETED)\n            time_taken = time.time() - start_time\n            hours, mins, secs = _to_hours_mins_secs(time_taken)\n            self._logger.info(\"Engine run complete. Time taken %02d:%02d:%02d\" % (hours, mins, secs))\n\n        except BaseException as e:\n            self._logger.error(\"Engine run is terminating due to exception: %s.\", str(e))\n            self._handle_exception(e)\n\n        return self.state\n", "path": "ignite/engine/engine.py"}]}