2.24. מנהלי הקשר#

פקודת ה-with מריצה קוד הכנה, אחר כך גוף, ואחר כך קוד פירוק – עם הבטחה שהפירוק ירוץ גם כאשר הגוף נכשל באמצע. צמד המתודות שמספק את ההכנה ואת הפירוק נקרא מנהל הקשר.

הצורה היא:

with <expression> as <name>:
    <body>

הביטוי מחזיר מנהל הקשר. Python קוראת למתודה __enter__ שלו, אופציונלית מקשרת את התוצאה ל-<name>, מריצה את הגוף, ואחר כך קוראת ל-__exit__ – בין אם הגוף הושלם כרגיל ובין אם זרק חריגה.

Flow diagram: __enter__ runs first, then the body; the body either completes normally or raises; either way, __exit__ runs at the end.

__exit__ רץ בסוף הבלוק בכל מצב שיקרה בתוכו.#

2.24.1. שימוש במנהל הקשר#

הדוגמה הקנונית היא פתיחת קובץ:

with open("data.txt") as f:
    text = f.read()

# f is now closed, even if read() failed

open() מחזיר אובייקט קובץ שהוא בעצמו מנהל הקשר; __enter__ מחזיר את הקובץ, ו-__exit__ סוגר אותו. בלוק ה-with הופך את ”תמיד לסגור את הקובץ בסיום“ לברירת מחדל במקום למשהו שהקורא צריך לזכור.

2.24.1.1. מנהלי הקשר מרובים#

פקודת with יחידה יכולה להיכנס למספר מנהלי הקשר בבת אחת, מופרדים בפסיקים:

with open("input.txt") as src, open("output.txt", "w") as dst:
    dst.write(src.read())

שקול לשני בלוקי with מקוננים, אך שטוח יותר. נכנסים למנהלים משמאל לימין ויוצאים מהם בסדר הפוך; אם __enter__ של המנהל הימני זורק חריגה, ה-__exit__ של המנהל השמאלי עדיין רץ.

2.24.2. כתיבת מנהל הקשר#

כל מחלקה עם מתודות __enter__ ו-__exit__ עובדת כמנהל הקשר:

class Section:
    def __init__(self, label):
        self.label = label

    def __enter__(self):
        print("---", self.label, "---")
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        print("--- end", self.label, "---")
        return False

with Section("setup"):
    print("doing the work")

פלט:

--- setup ---
doing the work
--- end setup ---

__exit__ מקבל שלושה ארגומנטים המתארים את החריגה שסיימה את הבלוק, או שלושה ערכי None אם הבלוק הושלם כרגיל. החזרת False (או None) מאפשרת לכל חריגה להתפשט לאחר הפירוק; החזרת True תבלע אותה.

השתמשו במנהלי הקשר עבור כל משאב שיש לו מחזור חיים של ”פתיחה / סגירה“ או ”השגה / שחרור“ – לא רק קבצים. הדפוס שומר את הניקוי מצומד להכנה בנקודה שבה שניהם מוצגים, כך שסגירה נשכחת באמצע פונקציה ארוכה אינה יכולה לדלוף את המשאב.