Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use contextlib.suppress as opposed to try/except with pass?

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
>>> 
like image 681
Markus Meskanen Avatar asked Jan 02 '16 14:01

Markus Meskanen


People also ask

What is suppress in Python?

To suppress an exception means that we will not handle the exception explicitly and it shouldn't cause the program to terminate. Using the try-except blocks and the pass statement in python, we can suppress the exceptions in python. The pass statement is used as a null statement. When executed, it does nothing.

What does Python except pass do?

The except:pass construct essentially silences any and all exceptional conditions that come up while the code covered in the try: block is being run.

How do you bypass Python errors?

Using Try Exceptblock to catch the ZeroDivisionError exception and ignore it. In the above code, we catch the ZeroDivisionError exception and use pass to ignore it. So, when this exception happens, nothing will be thrown and the program will just keep running by ignoring the zero number.


2 Answers

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.

like image 62
jfs Avatar answered Oct 18 '22 03:10

jfs


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).

like image 28
rgacote Avatar answered Oct 18 '22 03:10

rgacote