0% found this document useful (0 votes)
8 views

Lecture 29-30-Context Manager

Uploaded by

f2019065117
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

Lecture 29-30-Context Manager

Uploaded by

f2019065117
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 22

WHAT IS A CONTEXT?

Oxford dictionary: The circumstances that form the setting for an event, statement, or
idea, and in terms of which it can be fully understood.

In Python: the state surrounding a section of code

# module.py
global scope
f = open('test.txt', 'r') f → a file object
print(f.readlines())

f.close()

when print(f.readlines()) runs, it has a context in which it runs

→ global scope
Managing the context of a block of code

Consider the open file example: # module.py

f = open('test.txt', 'r') perform_work(f)


f.close()

There could be an exception before we close the file → file remains open!

Need to better "manage" the context that perform_work(f) needs

f = open('test.txt', 'r')

try:
perform_work(f)
finally:
f.close()

this works → writing try/finally every time can get cumbersome


→ too easy to forget to close the file
Context Managers
→ create a context (a minimal amount of state needed for a block of code)

→ execute some code that uses variables from the context

→ automatically clean up the context when we are done with it

→ enter context → open file


→ work within context → read the file
→ exit context → close the file
EXAMPLE
with open('test.txt', 'r') as f: create the context → open file

print(f.readlines()) work inside the context

exit the context → close file

Context managers manage data in our scope → on entry


→ on exit

Very useful for anything that needs to provide Enter / Exit Start / Stop Set / Reset

→ open / close file


→ start db transaction / commit or abort transaction
→ set decimal precision to 3 / reset back to original precision
try…finally…

The finally section of a try always executes


try:

except: always executes

even if an exception occurs in except block
finally:

Works even if inside a function and a return is in the try or except blocks

Very useful for writing code that should execute no matter what happens

But this can get cumbersome!

There has to be a better way!


Pattern
create some object

do some work with that object

clean up the object after we're done using it

We want to make this easy

→ automatic cleanup after we are done using the object


Context Managers PEP 343
OBJECT RETURNED FROM CONTEXT
(OPTIONAL)

with context as obj_name:


# with block (can use obj_name)

# after the with block, context is cleaned up automatically

Example
with open(file_name) as f: enter the context (optional) an object is returned
# file is now open
exit the context
# file is now closed
The context management protocol

Classes implement the context management protocol by implementing two methods:

__enter__ setup, and optionally return some object


__exit__ tear down / cleanup

over simplified
with CtxManager() as obj: # do mgr = CtxManager() obj =
something exception handling
# done with context mgr.__enter__() try:
# do something
finally:
# done with context
mgr.__exit__()
Use Cases
Very common usage is for opening a file (creating resource) and closing the file (releasing resource)

Context managers can be used for much more than creating and releasing resources

Common Patterns

• Open – Close
• Lock – Release
• Change – Reset
• Start – Stop
• Enter – Exit

Examples
• file context managers
• Decimal contexts
How Context Protocol Works class MyClass:
def __init__(self): # init class
works in conjunction with a with statement

my_obj = MyClass() def __enter__(self): return obj


works as a regular class
__enter__, __exit__ were not called def __exit__(self, + …):
# clean up obj

with MyClass() as obj:


→ creates an instance of MyClass → no associated symbol, but an instance exists
→ calls my_instance.__ enter__() → my_instance
→ return value from __enter__ is assigned to obj
(not the instance of MyClass that was created)

after the with block, or if an exception occurs inside the with block:
→ my_instance.__exit__ is called
Scope of with block
The with block is not like a function or a comprehension

The scope of anything in the with block (including the object returned from __enter__) is in the same scope

as the with statement itself

f is a symbol in global scope


# module.py

with open(fname) as f:
row = next(f)
row
i
s

a
l
s
The __enter__ method
def __enter__(self):

This method should perform whatever setup it needs to

It can optionally return an object → as returned_obj

That's all there is to this method


The __exit__ Method

More complicated…

Remember the finally in a try statement? → always runs even if an exception occurs

__exit__ is similar → runs even if an exception occurs in with block

But should it handle things differently if an exception occurred?

→ Maybe → so it needs to know about any exceptions that occurred

→ it also needs to tell Python whether to silence the exception, or let it propagate
The __exit__ Method
with MyContext() as obj:
raise ValueError

print ('done')

Scenario 1
__exit__ receives error, performs some clean up and silences error

print statement runs

no exception is seen

Scenario 2
__exit__ receives error, performs some clean up
and let's error propagate

print statement does not run

the ValueException is seen


The __exit__ method
Needs three arguments: → the exception type that occurred (if any, None otherwise)
→ the exception value that occurred (if any, None otherwise)
→ the traceback object if an exception occurred (if any, None otherwise)

Returns True or False: → True = silence any raised exception


→ False = do not silence a raised exception

def __exit__(self, exc_type, exc_value, exc_trace):


# do clean up work here
return True # or False

ValueError Traceback (most recent call last)


<ipython-input-14-39a69b57f322> in <module>()
1 with MyContext() as obj:
----> 2 raise ValueError
Pattern: Open - Close

Open File
operate on open file
Close File

Open socket operate


on socket
Close socket
Pattern: Start - Stop

Start database transaction

perform database operations

Commit or rollback transaction

Start timer

perform operations

Stop timer
Pattern: Lock - Release

acquire thread lock

perform some operations release

thread lock
Pattern: Change - Reset

change Decimal context precision

perform some operations using the new precision reset

Decimal context precision back to original value

redirect stdout to a file

perform some operations that write to stdout

reset stdout to original value

You might also like