If you're using Python 3.4+, select.epoll already supports context — you're clear to just write with epoll() as E: … and everything will be OK. The epoll descriptor will get properly closed, detached, etc.

But if you're operating on legacy 2 or ≤3.3 systems, writing bilingual code, etc., you might need to write a shim.

Thankfully, this is straightforward:

import select
if hasattr(select.epoll, '__enter__'):
	epoll_with = select.epoll
else:
	class epoll_with:
		'''contextlib wrapper for python2's epoll'''
		def __init__(self, *args, **kwargs):
			self._E = select.epoll(*args, **kwargs)
		def __enter__(self):
			return self._E
		def __exit__(self, exc_type, exc_value, traceback):
			self._E.close()

with epoll_with() as E:
	E.register(fd, flags)
	…

Note that this isn't a true "polyfill" yet: the same class can't be used both directly and as a contextmanager (at least not in Python 2/≤3.3). I'll update this post with a proper polyfill at some point, but doing is non-trivial because “TypeError: type 'select.epoll' is not an acceptable base type”.

Leave a Reply

Your email address will not be published. Required fields are marked *