2.24. Manajer konteks

Pernyataan with menjalankan kode setup, kemudian isi, kemudian kode teardown -- dengan jaminan bahwa teardown berjalan bahkan ketika isi gagal di tengah jalan. Pasangan metode yang menyediakan setup dan teardown disebut manajer konteks.

Bentuknya adalah:

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

Ekspresi mengembalikan manajer konteks. Python memanggil metode __enter__-nya, secara opsional mengikat hasilnya ke <name>, menjalankan isi, kemudian memanggil __exit__ -- baik isi selesai secara normal atau memunculkan pengecualian.

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

__exit__ berjalan di akhir blok apapun yang terjadi di dalamnya.

2.24.1. Menggunakan manajer konteks

Contoh kanonik adalah membuka file:

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

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

open() mengembalikan objek file yang merupakan manajer konteks itu sendiri; __enter__ mengembalikan file, dan __exit__ menutupnya. Blok with membuat "selalu tutup file setelah selesai" menjadi default daripada sesuatu yang harus diingat pemanggil.

2.24.1.1. Beberapa manajer konteks

Satu pernyataan with dapat memasuki beberapa manajer konteks sekaligus, dipisahkan dengan koma:

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

Setara dengan dua blok with bersarang, tetapi lebih datar. Manajer dimasuki dari kiri ke kanan dan keluar dalam urutan terbalik; jika __enter__ pada manajer kanan memunculkan pengecualian, __exit__ manajer kiri tetap berjalan.

2.24.2. Menulis manajer konteks

Kelas apa pun dengan metode __enter__ dan __exit__ bekerja sebagai manajer konteks:

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")

Output:

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

__exit__ menerima tiga argumen yang menggambarkan pengecualian yang mengakhiri blok, atau tiga nilai None jika blok selesai secara normal. Mengembalikan False (atau None) membiarkan pengecualian apa pun menyebar setelah teardown; mengembalikan True akan menelannya.

Gunakan manajer konteks untuk sumber daya apa pun yang memiliki siklus hidup "buka / tutup" atau "ambil / lepas" -- bukan hanya file. Pola ini menjaga pembersihan dipasangkan dengan setup di titik di mana keduanya diperkenalkan, sehingga penutupan yang terlupakan di tengah fungsi panjang tidak dapat membocorkan sumber daya.