Python Concepts/With Statement

From Wikiversity
Jump to navigation Jump to search

Objective[edit | edit source]

  • Learn about the with statement, its purpose, and its relationship with the try statement.
  • Learn how and when to use the with statement.
  • Learn how to create objects that can be used with the with statement.

Lesson[edit | edit source]

The With Statement[edit | edit source]

The with statement is an error handling statement, similar to the try statement. The with statement is used to cleanup objects automatically. This helps reduce the amount of code that needs to be written, since the finally statement and the object's manually written cleanup is omitted.

To use the with statement, you'll need to specify an object you want to use followed by the as statement, which then ends with the variable name of that object. Here is an example using the with statement, assuming that the file hello.txt has the sentence Hello, world! in it.

with open("hello.txt", "r") as file:
    print(file.read())
Hello, world!


An example using the try, except, and finally statements. Again, it assumes that the file hello.txt has the sentence Hello, world! in it.

try:
    file = open("hello.txt", "r")
    print(file.read())
except IOError:
    print("An I/O error has occurred!")
except:
    print("An unknown error has occurred!")
finally:
    file.close()
Hello, world!


However, if an error occurs while the file is open, the file will not be closed. Previously, one would have to write a try...finally block to ensure a proper cleanup of objects, which would require a lot more work and sacrifice readability.

Examples[edit | edit source]

When using Python's decimal module[edit | edit source]

Normal exit[edit | edit source]

This example shows how context is restored after exiting the with statement in operations using Python's decimal module.

from decimal import *

import sys

print ('1. current precision =', getcontext().prec)

with localcontext(Context(prec=55)) as ctx:
    s = ctx.sqrt(Decimal(10)) # This uses ctx.prec
    print ('    2a. s =', s)
    s = Decimal(10).sqrt() # This uses getcontext().prec
    print ('    2b. s =', s)
    print ('    2c. ctx.prec =',ctx.prec)
    print ('    2d. current precision =', getcontext().prec)

s = +s
print ('3. s =',s)
print ('4. current precision =', getcontext().prec)
print ('5. ctx.prec =',ctx.prec)
1. current precision = 28
    2a. s = 3.162277660168379331998893544432718533719555139325216827
    2b. s = 3.162277660168379331998893544432718533719555139325216827
    2c. ctx.prec = 55
    2d. current precision = 55
3. s = 3.162277660168379331998893544
4. current precision = 28 # Restored.
5. ctx.prec = 55 # Unchanged.

Exit after exception[edit | edit source]

This example shows that context is restored after exiting the with statement because of an exception.

error = ''
try:
  with localcontext() as ctx:
    print ('    6a. getcontext().prec =', getcontext().prec)
    ctx.prec = 55
    print ('    6b. getcontext().prec =', getcontext().prec)
    s = ctx.sqrt(Decimal(10))
    print ('    6c. s =',s)
    s = Decimal(10).sqrt()
    print ('    6d. s =',s)
    s = Decimal(-10).sqrt()
    print ('    6e. s =',s)
except:
  error = sys.exc_info()

print ('7. error =', error)
print ('8. precision =', getcontext().prec)
    6a. getcontext().prec = 28
    6b. getcontext().prec = 55 # Same as context ctx.
    6c. s = 3.162277660168379331998893544432718533719555139325216827
    6d. s = 3.162277660168379331998893544432718533719555139325216827
7. error = (<class 'decimal.InvalidOperation'>, 
            InvalidOperation([<class 'decimal.InvalidOperation'>],), 
            <traceback object at 0x1018c4f88>)
8. precision = 28 # Restored.

Assignments[edit | edit source]

Further Reading or Review[edit | edit source]

Completion status: this resource is just getting off the ground. Please feel welcome to help!

References[edit | edit source]

1. Python's documentation:

"with-statement"


2. Python's methods:

"decimal.localcontext", "decimal.Context"


3. Python's built-in functions: