Why use contextlib.suppress as opposed to try/except with pass?
Question:
Why would one use contextlib.suppress
to suppress an exception, instead of try
/except
with a pass
?
There is no difference in the amount of characters between these two methods (if anything, suppress
has more characters), and even though code is often counted in LOC instead of characters, suppress
also seems to be much slower than try
/except
in both cases, when an error is raised and when it’s not:
Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:27:37) [MSC v.1900 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> from timeit import timeit
>>> # With an error
>>> timeit("""with suppress(ValueError):
x = int('a')""", setup="from contextlib import suppress")
1.9571568971892543
>>> timeit("""try:
x = int('a')
except ValueError:
pass""")
1.0758466499161656
>>> # With no error
>>> timeit("""with suppress(ValueError):
x = int(3)""", setup="from contextlib import suppress")
0.7513525708063895
>>> timeit("""try:
x = int(3)
except ValueError:
pass""")
0.10141028937128027
>>>
Answers:
Conceptually, for me, the contextlib.suppress approach allows me to handle errors that are likely to occur (such as attempting to remove a file that may not actually be there). try/except then becomes a more active handling of ‘this should not happen’ events (such as a divide by 0 or inability to open a few to which I want to write).
It is two lines less code without sacrificing readability.
It might be especially convenient for nested or consecutive code blocks. Compare:
try:
a()
try:
b()
except B:
pass
except A:
pass
vs.:
with suppress(A):
a()
with suppress(B):
b()
It also allows to express the intent:
with suppress(SpecificError): do_something()
says don’t propagate the error if it is raised while doing something
try: do_something() except SpecificError: pass
says do something and don’t propagate the error if it is raised
It is less important because most people won’t notice the difference.
Why would one use contextlib.suppress
to suppress an exception, instead of try
/except
with a pass
?
There is no difference in the amount of characters between these two methods (if anything, suppress
has more characters), and even though code is often counted in LOC instead of characters, suppress
also seems to be much slower than try
/except
in both cases, when an error is raised and when it’s not:
Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:27:37) [MSC v.1900 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> from timeit import timeit
>>> # With an error
>>> timeit("""with suppress(ValueError):
x = int('a')""", setup="from contextlib import suppress")
1.9571568971892543
>>> timeit("""try:
x = int('a')
except ValueError:
pass""")
1.0758466499161656
>>> # With no error
>>> timeit("""with suppress(ValueError):
x = int(3)""", setup="from contextlib import suppress")
0.7513525708063895
>>> timeit("""try:
x = int(3)
except ValueError:
pass""")
0.10141028937128027
>>>
Conceptually, for me, the contextlib.suppress approach allows me to handle errors that are likely to occur (such as attempting to remove a file that may not actually be there). try/except then becomes a more active handling of ‘this should not happen’ events (such as a divide by 0 or inability to open a few to which I want to write).
It is two lines less code without sacrificing readability.
It might be especially convenient for nested or consecutive code blocks. Compare:
try:
a()
try:
b()
except B:
pass
except A:
pass
vs.:
with suppress(A):
a()
with suppress(B):
b()
It also allows to express the intent:
with suppress(SpecificError): do_something()
says don’t propagate the error if it is raised while doing somethingtry: do_something() except SpecificError: pass
says do something and don’t propagate the error if it is raised
It is less important because most people won’t notice the difference.