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.