--- title: Another way to make Python web app do concurrency date: 2014-09-11 12:13:12.192278 UTC --- I'm developing a Python web app that emulate [WifiDog](http://dev.wifidog.org/) for remote demo purpose. It is not just a normal web app because it has to run 2 jobs as the same time: - Run as a webserver, to redirect user visit to the URL of WifiDog's remote Auth Server. - Periodically report system state to Auth Server as a normal HTTP request. Make the first one is easy. The web part actually don't have much thing to do. It only builds some URL and redirect user to. A small script based on [Bootle](http://bottlepy.org) is enough. What make me concern is the second requirement. Normally, when I build a website on [Django](https://www.djangoproject.com/) or [Flask](http://flask.pocoo.org/) and I need the web do some periodic task, I just use [Celery](http://www.celeryproject.org/). But here I don't want to use Celery because Celery require me to run another command (`celery`) beside the main one (which is to launch my web app). Using Celery also means that I have to install more programs like RabbitMQ. It is a waste for just a small, simple web app. So I start looking to some Python libraries, especially it would be the best if it uses Python built-in stuff. I can use `thread` but it is not so recommended. I also have [bad experience](http://quan.hoabinh.vn/blog/2014/6/4/flask-sqlalchemy-consuming-100-cpu-with-multi-thread-wsgi-server) with web server in multi-threaded enviroment so I want to avoid it to save my hair. At the same time, I want to use the lastest software, Python v3.4. Hearing some buzz around Python's new __asyncio__ feature, I'm really curious and want to try it. [![Asyncio](http://asyncioaggregator.s3.amazonaws.com/content_submit/Screen_Shot_2014-05-09_at_11.14.12_AM.png)](http://asyncio.org/) After many days research and try, I found a way to combine a WSGI-compliant web app with _asyncio_ to do periodic job while serving a web. To archive this, I need [aiowsgi](https://aiowsgi.readthedocs.org/) as a WSGI server. Here is the example code: ```python import asyncio import aiowsgi from wifidemo import setting from wifidemo.views import app # This is the periodic task def ping(loop): # Do something # Do again after each 40s loop.call_later(40, ping, loop) if __name__ == '__main__': loop = asyncio.get_event_loop() loop.call_soon(ping, loop) aiowsgi.serve(app, loop=loop, host=setting.GATEWAY_ADDRESS, port=setting.GATEWAY_PORT) ``` So the key here is the _aiowsgi_ package. With a normal WSGI, you have no way to pass `loop` variable of _asyncio_ and thus, cannot work with _asyncio_. Though you can find something related to web and _asyncio_ in PyPI, but most of them are just a web microframework, using _asyncio_ internally, hidden and expose no _asyncio_ handle explicitly to connect with another task (as the `loop` variable above is needed to connect between `ping` and `aiowsgi.serve`).