Nikolaus Rath dixit (2011-10-19, 22:19):
That said, do you have a suggestion for Python 2.7 as well? Maybe something like a cleanup error handler?
As Sven noted, the error handler proposed by me is redundant. Such ones would be redundant too, IMHO. The appropriate place to catch cleanup errors would be a cleanup callback itself.
And -- according to another Sven's idea -- callbacks could be registered together with arguments, e.g.:
def closing_callback(stream): try: stream.close() except Exception: log.critical('Hm, something wrong...', exc_info=True) with CleanupMagager() as cm: xfile = open(x) cm.register(closing_callback, xfile) ...
An improved (and at the same time simplified) implementation (being also a recipe for Python 2.x, though this list is about ideas for Py3.x):
class CleanupManager(object): def __init__(self, initial_callbacks=()): self.cleanup_callbacks = list(initial_callbacks) def register(self, callback, *args, **kwargs): self.cleanup_callbacks.append((callback, args, kwargs)) def __enter__(self): return self def __exit__(self, exc_type, exc, tb): self._next_callback() def _next_callback(self): if self.cleanup_callbacks: callback, args, kwargs = self.cleanup_callbacks.pop() try: callback(*args, **kwargs) finally: # all cleanup callbacks to be used # Py3.x: all errors to be reported self._next_callback()
I hope it implements well what you explained... I'm not sure if it is worth to be added to the standard library (in the case of your primary example I'd rather prefer that try-finally nested structure) -- though in some cases it may become really useful:
with CleanupMagager() as cm: ... cm.register(foo) ... if cond: cm.register(bar) else: cm.register(spam) for x in y: cm.register(baz, x) ...