Supprimer Rendre public Rendre privé Add tags Delete tags
  Ajouter un tag   Annuler
  Supprimer le tag   Annuler
  • • DevOps notes •
  •  
  • Tags
  • Connexion

Context managers/shaare/wo-q7g

  • python
  • python

Context Managers

  • When opening files or acquiring locks, resources must be released even if errors occur.
  • Manual try...finally ensures cleanup but adds boilerplate and potential for mistakes.
  • Forgetting to initialize the resource variable or to call cleanup in every exit path leads to leaks, deadlocks, or corrupted data.
  • Cleaner patterns reduce noise and risk in automation scripts.
f = None

try:
    f = open("my_log.txt", "w")
    f.write("First line\n")
    # Simulate an error
    result = 1 / 0
    f.write("Second line\n")
except:
    print("Error has occurred.")
finally:
    if f:
        print("Closing file.")
        f.close()

print(f"File closed: {f.closed}")

The with Statement Simplifies Cleanup

  • The with statement handles setup and teardown automatically for context managers.
  • For file I/O, with open(...) as f: guarantees f.close() on block exit, even if an exception is raised.
  • Syntax is concise and idiomatic, reducing boilerplate and improving readability.

Common Context Manager Examples

  • Files: with open(...) as f: for automatic file closing.
  • Locks: with threading.Lock(): acquires and releases locks safely.
  • Tempfiles/Dirs: with tempfile.TemporaryDirectory() as d: creates and cleans up temporary directories.
  • Context managers from the standard library cover most resource-management needs.
f = None

try:
    with open("my_log.txt", "w") as f:
        f.write("First line\n")
        # Simulate an error
        result = 1 / 0
        f.write("Second line\n")
except:
    print("Error has occurred.")

print(f"File closed: {f.closed}")
import tempfile, os

dir_name = None

with tempfile.TemporaryDirectory() as tempdir:
    print(f"Created temp dir: {tempdir}")

    dir_name = tempdir
    test_file = os.path.join(tempdir, "test.txt")

    with open(test_file, "w") as file:
        file.write("Hello from temp directory.")

    print(f"Files inside temp dir: {os.listdir(tempdir)}")

try:
    contents = os.listdir(dir_name)
    print(f"Contents of {dir_name}: {contents}")
except FileNotFoundError as e:
    print(f"Expected error accessing removed directory: {e}")

Custom Resource Management: Writing Context Managers

  • Whenever you need custom setup/teardown logic, you can write your own Context Manager.
  • A context manager ensures that teardown always runs, even if errors occur in the block.
  • Two approaches: implement __enter__/__exit__ in a class or use the simpler generator-based decorator.
class MyContextManager:
    def __init__(self, timeout):
        self.timeout = timeout

    def __enter__(self):
        print("Setup complete")
        return "a simple value"

    def __exit__(self, exception_type, exception_value, traceback):
        print(f"Teardown")

        # Commenting out since we replaced *args for explicit
        # exception_type, exception_value, traceback parameters

        # for arg in args:
        #     print(arg)

        return False

with MyContextManager(timeout=30) as cm:
    print(cm)
    print("Inside the block")
    raise ValueError("Simulated problem")

The @contextlib.contextmanager Decorator

  • Provided by the contextlib module to turn a generator into a context manager.
  • Decorated function needs exactly one yield.
  • Code before yield runs as __enter__; code after (or in finally) runs as __exit__.
  • Simplifies many common patterns without writing a full class.

Generator Structure for @contextmanager

  • Wrap the yield in try...finally to ensure teardown even on errors.
  • The value yielded is bound to as var in the with statement (if used).
  • You can catch exceptions inside the generator if you want to suppress them.
import os
from contextlib import contextmanager

@contextmanager
def change_directory(destination):
    """
    Temporarily switch into destination. If the directory does not exist,
    it is created just before the switch.

    Args:
        destination (str): Path to the directory that should become the working directory
    """

    origin_dir = os.getcwd()

    try:
        print(f"Changing into {destination}")
        os.makedirs(destination, exist_ok=True)
        os.chdir(destination)
        yield os.getcwd()
    finally:
        print(f"Reverting to original dir: {origin_dir}")
        os.chdir(origin_dir)

print(f"Start: {os.getcwd()}")

with change_directory("temp_dir") as new_dir:
    print(f"Inside: {new_dir}")

print(f"End: {os.getcwd()}")
2 months ago Permalien
cluster icon
  • Typing classes : Introduction As our Python automation projects grow, defining custom classes helps model complex objects and should be reflected in type hints for cl...
  • Working with JSON files : Working with JSON files JSON is the standard format for data exchange in web services and cloud APIs. Python’s built-in json module provides function...
  • Variables, comments : Variables: Naming Values Naming Guidelines: Must start with a letter or underscore (_) and can contain letters, numbers, and underscores. Use snake_...
  • Parametrized Tests : Parametrized Tests Introduction Often, we need to test the same logic with different inputs and outputs, such as validating various IP address or hos...
  • Generators and Lazy Pipelines : Generators and Lazy Pipelines You can chain generator functions to form multi-stage data pipelines that process items one at a time. No intermediat...


(110)
Filtrer par liens sans tag
Replier Replier tout Déplier Déplier tout Êtes-vous sûr de vouloir supprimer ce lien ? Êtes-vous sûr de vouloir supprimer ce tag ? Le gestionnaire de marque-pages personnel, minimaliste, et sans base de données par la communauté Shaarli