[Python-Dev] Merging PEP 310 and PEP 340-redux?
Shane Hathaway
shane at hathawaymix.org
Fri May 13 03:51:26 CEST 2005
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
More information about the Python-Dev
mailing list