Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to understand python with statement and context managers

Tags:

I am trying to understand the with statement. I understand that it is supposed to replace the try/except block.

Now suppose I do something like this:

try:    name = "rubicon" / 2  # to raise an exception except Exception as e:    print("No, not possible.") finally:    print("OK, I caught you.") 

How do I replace this with a context manager?

like image 289
user444997 Avatar asked Sep 12 '10 04:09

user444997


People also ask

What is the context manager statement in Python?

Python provides an easy way to manage resources: Context Managers. The with keyword is used. When it gets evaluated it should result in an object that performs context management. Context managers can be written using classes or functions(with decorators).

Why you should use context managers in Python?

Context managers allow you to allocate and release resources precisely when you want to. The most widely used example of context managers is the with statement. Suppose you have two related operations which you'd like to execute as a pair, with a block of code in between.

What is the use of the with context manager?

They allow you to provide and reuse common setup and teardown code. In other words, with context managers, you can perform any pair of operations that needs to be done before and after another operation or procedure, such as: Open and close. Lock and release.


2 Answers

with doesn't really replace try/except, but, rather, try/finally. Still, you can make a context manager do something different in exception cases from non-exception ones:

class Mgr(object):     def __enter__(self): pass     def __exit__(self, ext, exv, trb):         if ext is not None: print "no not possible"         print "OK I caught you"         return True  with Mgr():     name='rubicon'/2 #to raise an exception 

The return True part is where the context manager decides to suppress the exception (as you do by not re-raising it in your except clause).

like image 195
Alex Martelli Avatar answered Sep 23 '22 19:09

Alex Martelli


The contextlib.contextmanager function decorator provides a handy way of providing a context manager without the need to write a full-fledged ContextManager class of your own (with __enter__ and __exit__ methods, so you don't have to remember the arguments to the __exit__ method, or that the __exit__ method must return True in order to suppress the exception). Instead, you write a function with a single yield at the point you want the with block to run, and you trap any exceptions (that effectively come from the yield) as you normally would.

from contextlib import contextmanager @contextmanager def handler():     # Put here what would ordinarily go in the `__enter__` method     # In this case, there's nothing to do     try:         yield # You can return something if you want, that gets picked up in the 'as'     except Exception as e:         print "no not possible"     finally:         print "Ok I caught you"  with handler():     name='rubicon'/2 #to raise an exception 

Why go to the extra trouble of writing a context manager? Code re-use. You can use the same context manager in multiple places, without having to duplicate the exception handling. If the exception handling is unique to that situation, then don't bother with a context manager. But if the same pattern crops up again and again (or if it might for your users, e.g., closing a file, unlocking a mutex), it's worth the extra trouble. It's also a neat pattern to use if the exception handling is a bit complicated, as it separates the exception handling from the main line of code flow.

like image 31
Paul Price Avatar answered Sep 23 '22 19:09

Paul Price