Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of a context manager in python [duplicate]

Tags:

python

I'm reading http://eigenhombre.com/2013/04/20/introduction-to-context-managers/ .

In it:

Context managers are a way of allocating and releasing some sort of resource exactly where you need it. The simplest example is file access:

with file("/tmp/foo", "w") as foo:
    print >> foo, "Hello!"

This is essentially equivalent to:

foo = file("/tmp/foo", "w")
try:
    print >> foo, "Hello!"
finally:
    foo.close()

The article goes on to more explanation , but I'm still not sure I understand in simple terms their purpose. Can someone clarify. Also what is the "context"?

I have looked at Trying to understand python with statement and context managers , but again I'm not sure what the purpose of a context manager is? Is it just an alternative syntax for "try.. finally.." or is their some other purpose

like image 476
user1592380 Avatar asked Apr 11 '16 21:04

user1592380


1 Answers

What are context managers?

Context managers are there to aid with resources (although may be used for much more). The context is basically the resource.

Let's say you opened a file for writing:

f = open(path, "w")

You now have an open file handle. During the handling of your file, no other program can write to it. In order to let other programs write to it, you must close the file handle:

f.close()

But, before closing your file an error occured:

f = open(path, "w")
data = 3/0  # Tried dividing by zero. Raised ZeroDivisionError
f.write(data)
f.close()

What will happen now is that the function or entire program will exit, while leaving your file with an open handle. (CPython cleans handles on termination and handles are freed together with a program but you shouldn't count on that)

A with statement ensures that as soon as you leave it's indentation, it will close the file handle:

with open(path, "w") as f:
    data = 3/0  # Tried dividing by zero. Raised ZeroDivisionError
    f.write(data)
# Here, the file is already closed automatically, no matter what happened.

with statements may be used for many more things. For example: threading.Lock()

lock = threading.Lock()
with lock:  # Lock is acquired
   do stuff...
# Lock is automatically released.

Almost everything done with a context manager can be done with try: ... finally: ... but context managers are nicer to use, more comfortable, more readable and by implementing __enter__ and __exit__ provide an easy to use interface.


How are context managers implemented?

or What are __enter__ and __exit__?

Creating context managers is done by implementing __enter__() and __exit__() in a normal class.

__enter__() tells what to do when a context manager starts and __exit__() when a context manager exists (giving the exception to the __exit__() method if an exception occurred)

A shortcut for creating context managers can be found in contextlib. It wraps a generator as a context manager like so:

from contextlib import contextmanager

@contextmanager
def tag(name):
    print("<%s>" % name)
    yield
    print("</%s>" % name)

>>> with tag("h1"):
...    print("foo")
...
<h1>
foo
</h1>

Example taken from the Python docs.

like image 59
Bharel Avatar answered Nov 15 '22 19:11

Bharel