title: How to gracefully terminate an asyncio script with Ctrl-C?
body: <p>I've read every post I could find about how to gracefully handle a script with an asyncio event loop getting terminated with Ctrl-C, and I haven't been able to get any of them to work without printing one or more tracebacks as I do so. The answers are pretty much all over the place, and I haven't been able implement any of them into this small script:</p>
  
  <pre><code>import asyncio
  import datetime
  import functools
  import signal
  
  
  async def display_date(loop):
      end_time = loop.time() + 5.0
      while True:
          print(datetime.datetime.now())
          if (loop.time() + 1.0) &gt;= end_time:
              break
          await asyncio.sleep(1)
  
  
  def stopper(signame, loop):
      print("Got %s, stopping..." % signame)
      loop.stop()
  
  
  loop = asyncio.get_event_loop()
  for signame in ('SIGINT', 'SIGTERM'):
      loop.add_signal_handler(getattr(signal, signame), functools.partial(stopper, signame, loop))
  
  loop.run_until_complete(display_date(loop))
  loop.close()
  </code></pre>
  
  <p>What I want to happen is for the script to exit without printing any tracebacks following a Ctrl-C (or SIGTERM/SIGINT sent via <code>kill</code>). This code prints <code>RuntimeError: Event loop stopped before Future completed.</code> In the MANY other forms I've tried based on previous answers, I've gotten a plethora of other types of exception classes and error messages with no idea how to fix them. The code above is minimal right now, but some of the attempts I made earlier were anything but, and none of them were correct.</p>
  
  <p>If you're able to modify the script so that it terminates gracefully, an explanation of why your way of doing it is the <strong>right</strong> way would be greatly appreciated.</p>