Trying to implement 2 "threads" using `asyncio` module

Viewed 1031

I've played around with threading before in Python, but decided to give the asyncio module a try, especially since you can cancel a running task, which seemed like a nice detail. However, for some reason, I can't wrap my head around it.

Here's what I wanted to implement (sorry if I'm using incorrect terminology):

  • a downloader thread that downloads the same file every x seconds, checks its hash against the previous download and saves it if it's different.
  • a webserver thread that runs in the background, allowing control (pause, list, stop) of the downloader thread.

I used aiohttp for the webserver.

This is what I have so far:

class aiotest():

    def __init__(self):
        self._dl = None     # downloader future
        self._webapp = None # web server future
        self.init_server()

    def init_server(self):

        print('Setting up web interface')
        app = web.Application()
        app.router.add_route('GET', '/stop', self.stop)
        print('added urls')
        self._webapp = app

    @asyncio.coroutine
    def _downloader(self):
        while True:
            try:
                print('Downloading and verifying file...')
                # Dummy sleep - to be replaced by actual code
                yield from asyncio.sleep(random.randint(3,10))
                # Wait a predefined nr of seconds between downloads
                yield from asyncio.sleep(30)
            except asyncio.CancelledError:
                break

    @asyncio.coroutine
    def _supervisor(self):

        print('Starting downloader')
        self._dl = asyncio.async(self._downloader())

    def start(self):
        loop = asyncio.get_event_loop()
        loop.run_until_complete(self._supervisor())
        loop.close()

    @asyncio.coroutine
    def stop(self):
        print('Received STOP')
        self._dl.cancel()
        return web.Response(body=b"Stopping... ")

This class is called by:

t = aiotest()
t.start()

This doesn't work of course, and I feel that this is a horrible piece of code.

What's unclear to me:

  • I stop the downloader in the stop() method, but how would I go about stopping the webserver (e.g. in a shutdown() method)?
  • Does the downloader need a new event loop, or can I use the loop returned by asyncio.get_event_loop()?
  • Do I really need something like the supervisor for what I'm trying to implement? This seems so clunky. And how do I get supervisor to keep running instead of ending after a single execution as it does now?

One last, more general question: is asyncio supposed to replace the threading module (in the future)? Or does each have its own application?

I appreciate all the pointers, remarks and clarifications!

1 Answers
Related