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
”.