Context Managers

In Python, a context manager is an object that controls the environment in which a piece of code is executed. It provides a convenient way to manage resources such as file streams, network connections, and locks, which have certain states that need to be set up before the main code is run and cleaned up afterwards.

The context manager interface has two methods:

Example of a Custom Context Manager

class MyContextManager:
    def __init__(self, filename):
        self.filename = filename

    def __enter__(self):
        self.file = open(self.filename, 'r')
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()

Usage

with MyContextManager('myfile.txt') as f:
    data = f.read()
    print(data)

Threading

Locks implement the context manager API and are compatible with the with statement:

import threading
import logging

logging.basicConfig(level=logging.DEBUG,
                    format='(%(threadName)-10s) %(message)s',)

def worker_with(lock):
    with lock:
        logging.debug('Lock acquired via with')

def worker_not_with(lock):
    lock.acquire()
    try:
        logging.debug('Lock acquired directly')
    finally:
        lock.release()

if __name__ == '__main__':
    lock = threading.Lock()
    w = threading.Thread(target=worker_with, args=(lock,))
    nw = threading.Thread(target=worker_not_with, args=(lock,))

    w.start()
    nw.start()