Guido van Rossum wrote: > Going for all-out simplicity, I would like to be able to write these examples: > > class locking: > def __init__(self, lock): self.lock = lock > def __enter__(self): self.lock.acquire() > def __exit__(self, *args): self.lock.release() > > class opening: > def __init__(self, filename): self.filename = filename > def __enter__(self): self.f = open(self.filename); return self.f > def __exit__(self, *args): self.f.close()\ > > And do EXPR as VAR: BLOCK would mentally be translated into > > itr = EXPR > VAR = itr.__enter__() > try: BLOCK > finally: itr.__exit__(*sys.exc_info()) # Except sys.exc_info() isn't > defined by finally
If it's this simple, it should be possible to write something that combines the acquisition of multiple resources in a single statement. For example: with combining(opening(src_fn), opening(dst_fn, 'w')) as src, dst: copy(src, dst) I think the following class would do it. class combining: def __init__(self, *resources): self.resources = resources self.entered = 0 def __enter__(self): results = [] try: for r in self.resources: results.append(r.__enter__()) self.entered += 1 return results except: # exit resources before re-raising the exception self.__exit__() raise def __exit__(self, *args): last_exc = None # exit only the resources successfully entered to_exit = self.resources[:self.entered] while to_exit: r = to_exit.pop() try: r.__exit__(*args) except: # re-raise the exception after exiting the others last_exc = sys.exc_info() if last_exc is not None: raise last_exc[0], last_exc[1], last_exc[2] Would that work? Shane _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com