[Python-ideas] with None (Was: Re: Enhanced context managers with ContextManagerExit and None)
Serhiy Storchaka
storchaka at gmail.com
Tue Aug 13 16:48:22 CEST 2013
07.08.13 17:23, Kristján Valur Jónsson написав(ла):
> 2) The mechanism used in implementing ContextManagerExit above is easily extended to allowing a special context manager: None. This is useful for having _optional_ context managers. E.g. code like this:
> with performance_timer():
> do_work()
>
> def performance_timer():
> if profiling:
> return accumulator
> return None
>
> None becomes the trivial context manager and its __enter__ and __exit__ calls are skipped, along with their overhead.
+1 to this idea. Of course ExitStack is powerful tool but it is too
verbose for many simple cases.
Consider simple example:
file = open(...) if ... else None
file2 = open(...) if ... else None
process(file, file2, ...)
if file is not None:
file.close()
if file2 is not None:
file2.close()
This code is not exception-safe. There are some ways to write it right.
1. With try/finally and a check in finally block:
file = open(...) if ... else None
try:
file2 = open(...) if ... else None
try:
process(file, file2, ...)
finally:
if file2 is not None:
file2.close()
finally:
if file is not None:
file.close()
2. With a code duplication (note that process can be not a one-line call
of a function):
if ...:
with open(...) as file:
if ...:
with open(...) as file2:
process(file, file2, ...)
else:
process(file, None, ...)
else:
if ...:
with open(...) as file2:
process(None, file2, ...)
else:
process(None, None, ...)
3. With ExitStack:
import contextlib
with contextlib.ExitStack() as cm:
if ...:
file = open(...)
cm.enter_context(file)
else:
file = None
if ...:
file2 = open(...)
cm.enter_context(file2)
else:
file2 = None
process(file, file2, ...)
And when the with statement will support None as a "null-manager":
file = open(...) if ... else None
with file:
file2 = open(...) if ... else None
with file2:
process(file, file2, ...)
More information about the Python-ideas
mailing list