I've broken from our usual procedural form and used an object-oriented approach in the last example for two reasons. First, although it is possible to write a purely procedural style server with asyncio
, it requires a deeper understanding of co-routines than what we were able to provide here. If you're curious, then you can go through an example co-routine style echo server, which is in the asyncio
documentation at https://docs.python.org/3/library/asyncio-stream.html#asyncio-tcp-echo-server-streams.
The second reason is that this kind of class-based approach is generally a more manageable model to follow in a full system.
There is in fact a new module called selectors
in Python 3.4, which provides an API for quickly building an object-oriented server based on the IO primitives in the select
module (including poll
). The documentation and an example can be seen at https://docs.python.org/3.4/library/selectors.html.
There are other third-party event-driven frameworks available, popular ones are Tornado (www.tornadoweb.org) and circuits (https://github.com/circuits/circuits). Both are worth investigating for comparison, if you intend to choose a framework for a project.
Moreover, no discussion of Python asynchronous I/O would be complete without a mention of the Twisted framework. Until Python 3, this has been the go to solution for any serious asynchronous I/O work. It is an event-driven engine, with support for a large number of network protocols, good performance, and a large and active community. Unfortunately, it hasn't finished the jump to Python 3 yet (a view of the migration progress can be seen at https://rawgit.com/mythmon/twisted-py3-graph/master/index.html). Since we're focused squarely on Python 3 in this book, we decided to not include a detailed treatment of it. However, once it does get there, Python 3 will have another very powerful asynchronous framework, which will be well worth investigating for your projects.