title: How to reset an asyncio eventloop by a worker?
body: <p>I'm working with an <code>asyncio forever()</code> eventloop. Now I want to restart the loop (stop the loop and recreate a new loop) after a process or a signal or a change in a file, but I have some problems to do that:</p>
  <hr />
  <p>Here are three simplified code snippets in which demonstrate some coroutine workers and a coroutine loop restarter:</p>
  <hr />
  <p><em>#1st try:</em></p>
  <pre><code>import asyncio
  
  async def coro_worker(proc):
      print(f'Worker: {proc} started.')
      while True:
          print(f'Worker: {proc} process.')
          await asyncio.sleep(proc)
  
  async def reset_loop(loop):
      # Some process
      for i in range(5):  # Like a process.
          print(f'{i} counting for reset the eventloop.')
          await asyncio.sleep(1)
  
      main(loop)  # Expected close the current loop and start a new loop!
  
  def main(previous_loop=None):
      offset = 0
      if previous_loop is not None:  # Trying for close the last loop if exist.
          offset = 1  # An offset to change the process name.
          for task in asyncio.Task.all_tasks():
              print('Cancel the tasks')  # Why it increase up?
              task.cancel()
              # task.clear()
              # task.close()
              # task.stop()
  
          print(&quot;Done cancelling tasks&quot;)
          asyncio.get_event_loop().stop()
  
      process = [1 + offset, 2 + offset]
      loop = asyncio.get_event_loop()
      futures = [loop.create_task(coro_worker(proc)) for proc in process]
      futures.append(loop.create_task(reset_loop(loop)))
  
      try:
          loop.run_forever()
      except KeyboardInterrupt:
          pass
      except asyncio.CancelledError:
          print('Tasks has been canceled')
          main()  # Recursively
      finally:
          print(&quot;Closing Loop&quot;)
          loop.close()
  main()
  </code></pre>
  <p>Out[1]:</p>
  <pre><code>Worker: 1 started.
  Worker: 1 process.
  Worker: 2 started.
  Worker: 2 process.
  0 counting for reset the eventloop.
  Worker: 1 process.
  1 counting for reset the eventloop.
  Worker: 2 process.
  Worker: 1 process.
  2 counting for reset the eventloop.
  Worker: 1 process.
  3 counting for reset the eventloop.
  Worker: 2 process.
  Worker: 1 process.
  4 counting for reset the eventloop.
  Worker: 1 process.
  Cancel the tasks
  Cancel the tasks
  Cancel the tasks
  Done cancelling tasks
  Closing Loop
  Closing Loop
  Task exception was never retrieved
  future: &lt;Task cancelling coro=&lt;reset_loop() done, defined at reset_asycio.py:11&gt; exception=RuntimeError('Cannot close a running event loop',)&gt;
  Traceback (most recent call last):
    File &quot;reset_asycio.py&quot;, line 40, in main
      loop.run_forever()
    File &quot;/usr/lib/python3.6/asyncio/base_events.py&quot;, line 425, in run_forever
      raise RuntimeError('This event loop is already running')
  RuntimeError: This event loop is already running
  
  During handling of the above exception, another exception occurred:
  
  Traceback (most recent call last):
    File &quot;reset_asycio.py&quot;, line 17, in reset_loop
      main(loop)  # Expected close the current loop and start a new loop!
    File &quot;reset_asycio.py&quot;, line 48, in main
      loop.close()
    File &quot;/usr/lib/python3.6/asyncio/unix_events.py&quot;, line 63, in close
      super().close()
    File &quot;/usr/lib/python3.6/asyncio/selector_events.py&quot;, line 96, in close
      raise RuntimeError(&quot;Cannot close a running event loop&quot;)
  RuntimeError: Cannot close a running event loop
  Task was destroyed but it is pending!
  task: &lt;Task pending coro=&lt;reset_loop() running at reset_asycio.py:11&gt;&gt;
  reset_asycio.py:51: RuntimeWarning: coroutine 'reset_loop' was never awaited
    main()
  Task was destroyed but it is pending!
  task: &lt;Task pending coro=&lt;coro_worker() running at reset_asycio.py:4&gt;&gt;
  reset_asycio.py:51: RuntimeWarning: coroutine 'coro_worker' was never awaited
    main()
  Task was destroyed but it is pending!
  task: &lt;Task pending coro=&lt;coro_worker() running at reset_asycio.py:4&gt;&gt;
  Task was destroyed but it is pending!
  task: &lt;Task pending coro=&lt;coro_worker() running at reset_asycio.py:8&gt; wait_for=&lt;Future cancelled&gt;&gt;
  Task was destroyed but it is pending!
  task: &lt;Task pending coro=&lt;coro_worker() running at reset_asycio.py:8&gt; wait_for=&lt;Future cancelled&gt;&gt;
  </code></pre>
  <hr />
  <p><em>#2nd try:</em></p>
  <pre><code>.
  .
  .
  
  def main(previous_loop=None):
      offset = 0
      if previous_loop is not None:  # Trying for close the last loop if exist.
          previous_loop.stop()
          previous_loop.close()
          offset = 1  # An offset to change the process name.
  
      process = [1 + offset, 2 + offset]
      loop = asyncio.get_event_loop()
      futures = [loop.create_task(coro_worker(proc)) for proc in process]
      futures.append(loop.create_task(reset_loop(loop)))
  
      try:
          loop.run_forever()
      except KeyboardInterrupt:
          pass
      except asyncio.CancelledError:
          print('Tasks has been canceled')
          main()  # Recursively
      finally:
          print(&quot;Closing Loop&quot;)
          loop.close()
  main()
  </code></pre>
  <p>Out[2]:</p>
  <pre><code>Worker: 1 started.
  Worker: 1 process.
  Worker: 2 started.
  Worker: 2 process.
  0 counting for reset the eventloop.
  Worker: 1 process.
  1 counting for reset the eventloop.
  Worker: 2 process.
  Worker: 1 process.
  2 counting for reset the eventloop.
  Worker: 1 process.
  3 counting for reset the eventloop.
  Worker: 2 process.
  Worker: 1 process.
  4 counting for reset the eventloop.
  Worker: 1 process.
  Closing Loop
  Task exception was never retrieved
  future: &lt;Task finished coro=&lt;reset_loop() done, defined at reset_asycio.py:9&gt; exception=RuntimeError('Cannot close a running event loop',)&gt;
  Traceback (most recent call last):
    File &quot;reset_asycio.py&quot;, line 15, in reset_loop
      main(loop)  # Expected close the current loop and start new loop!
    File &quot;reset_asycio.py&quot;, line 21, in main
      previous_loop.close()
    File &quot;/usr/lib/python3.6/asyncio/unix_events.py&quot;, line 63, in close
      super().close()
    File &quot;/usr/lib/python3.6/asyncio/selector_events.py&quot;, line 96, in close
      raise RuntimeError(&quot;Cannot close a running event loop&quot;)
  RuntimeError: Cannot close a running event loop
  Task was destroyed but it is pending!
  task: &lt;Task pending coro=&lt;coro_worker() done, defined at reset_asycio.py:3&gt; wait_for=&lt;Future pending cb=[&lt;TaskWakeupMethWrapper object at 0x7efed846f138&gt;()]&gt;&gt;
  Task was destroyed but it is pending!
  task: &lt;Task pending coro=&lt;coro_worker() done, defined at reset_asycio.py:3&gt; wait_for=&lt;Future pending cb=[&lt;TaskWakeupMethWrapper object at 0x7efed846f048&gt;()]&gt;&gt;
  </code></pre>
  <hr />
  <p><em>#3rd try:</em></p>
  <pre><code>.
  .
  .
  
  def main(previous_loop=None):
      offset = 0
      if previous_loop is not None:  # Trying for close the last loop if exist.
          offset = 1  # An offset to change the process name.
          for task in asyncio.Task.all_tasks():
              print('Cancel the tasks')  # Why it increase up?
              task.cancel()
  
      process = [1 + offset, 2 + offset]
      loop = asyncio.get_event_loop()
      futures = [loop.create_task(coro_worker(proc)) for proc in process]
      futures.append(loop.create_task(reset_loop(loop)))
  
      try:
          loop.run_forever()
      except KeyboardInterrupt:
          pass
      except asyncio.CancelledError:
          print('Tasks has been canceled')
          main()  # Recursively
      finally:
          print(&quot;Closing Loop&quot;)
          loop.close()
  main()
  </code></pre>
  <p>Out[3]:</p>
  <pre><code>Worker: 1 started.
  Worker: 1 process.
  Worker: 2 started.
  Worker: 2 process.
  0 counting for reset the eventloop.
  Worker: 1 process.
  1 counting for reset the eventloop.
  Worker: 2 process.
  Worker: 1 process.
  2 counting for reset the eventloop.
  Worker: 1 process.
  3 counting for reset the eventloop.
  Worker: 2 process.
  Worker: 1 process.
  4 counting for reset the eventloop.
  Worker: 1 process.
  Cancel the tasks
  Cancel the tasks
  Cancel the tasks
  Closing Loop
  Worker: 2 started.
  Worker: 2 process.
  Worker: 3 started.
  Worker: 3 process.
  0 counting for reset the eventloop.
  1 counting for reset the eventloop.
  Worker: 2 process.
  2 counting for reset the eventloop.
  Worker: 3 process.
  3 counting for reset the eventloop.
  Worker: 2 process.
  4 counting for reset the eventloop.
  Cancel the tasks
  Cancel the tasks
  Cancel the tasks
  Cancel the tasks
  Cancel the tasks
  Cancel the tasks
  Closing Loop
  Worker: 2 started.
  Worker: 2 process.
  Worker: 3 started.
  Worker: 3 process.
  .
  .
  .
  </code></pre>
  <hr />
  <p>#Problem:</p>
  <ul>
  <li><p>In the <em>#3rd try</em>, apparently I've done it, but <code>print('Cancel the tasks')</code> increases up after each restarting, what's the reason?!</p>
  </li>
  <li><p>Is there a better approach to overcome this problem?</p>
  </li>
  </ul>
  <p>Forgive me for the long question I tried to simplify it!</p>
  <hr />
  <p>[NOTE]:</p>
  <ul>
  <li>I'm not looking for the <code>asyncio.timeout()</code></li>
  <li>I also tried with another thread in order to restart the eventloop with an unsuccessful result.</li>
  <li>I'm using <em>Python 3.6</em></li>
  </ul>