I'm developing a Python web app that emulate WifiDog 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 is enough. What make me concern is the second requirement. Normally, when I build a website on Django or Flask and I need the web do some periodic task, I just use Celery. 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 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.
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 as a WSGI server.
Here is the example code:
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
).