Traffine I/O

Bahasa Indonesia

2023-03-31

contextlib.contextmanager

Apa itu contextlib.contextmanager

contextlib.contextmanager adalah sebuah alat yang kuat di Python yang memungkinkan pengembang untuk membuat manajer konteks kustom mereka sendiri menggunakan fungsi sederhana dan decorator. Artikel ini memberikan panduan untuk memahami dan efektif menggunakan decorator contextmanager.

Memahami decorator contextmanager

Decorator contextmanager adalah bagian dari modul contextlib di Python. Ini memungkinkan Anda untuk mengubah fungsi generator sederhana menjadi manajer konteks, tanpa perlu mendefinisikan kelas lengkap dengan metode __enter__() dan __exit__(). Hal ini membuat proses membuat manajer konteks kustom lebih efisien dan tidak merepotkan.

Untuk menggunakan decorator contextmanager, Anda perlu mengimpornya dari modul contextlib:

python
from contextlib import contextmanager

Membuat Manajer Konteks Kustom dengan contextmanager

Untuk membuat manajer konteks kustom menggunakan contextmanager, Anda perlu mendefinisikan fungsi generator yang menghasilkan satu nilai saja. Bagian dari fungsi sebelum pernyataan yield akan dieksekusi ketika metode __enter__() dipanggil, dan bagian setelah pernyataan yield akan dieksekusi ketika metode __exit__() dipanggil.

Berikut adalah contoh manajer konteks sederhana yang menggunakan contextmanager:

python
from contextlib import contextmanager

@contextmanager
def managed_resource():
    print("Acquiring resource")
    resource = "Resource acquired"
    try:
        yield resource
    finally:
        print("Releasing resource")
        resource = None

with managed_resource() as res:
    print(res)

Ketika kode ini dijalankan, Anda akan melihat output berikut:

Acquiring resource
Resource acquired
Releasing resource

Contoh dan Aplikasi di Dunia Nyata

contextlib.contextmanager dapat digunakan dalam berbagai skenario kehidupan nyata untuk mengelola resource secara efisien dan menangani pengecualian. Berikut adalah beberapa contoh aplikasinya:

  • Mengelola operasi I/O file
    Kasus penggunaan umum untuk manajer konteks adalah mengelola operasi I/O file, memastikan bahwa file dibuka, dibaca atau ditulis, dan ditutup dengan benar.
python
from contextlib import contextmanager

@contextmanager
def open_file(file_path, mode):
    file = open(file_path, mode)
    try:
        yield file
    finally:
        file.close()

file_path = "example.txt"

with open_file(file_path, "w") as file:
    file.write("Hello, world!")

with open_file(file_path, "r") as file:
    content = file.read()
    print(content)
Hello, world!
  • Mengelola koneksi database
    Mengelola koneksi dan transaksi dengan database adalah kasus penggunaan umum lainnya untuk manajer konteks. Dalam contoh ini, kita menunjukkan bagaimana menggunakan manajer konteks untuk menangani koneksi dan transaksi database SQLite.
python
import sqlite3
from contextlib import contextmanager

@contextmanager
def sqlite_connection(db_path):
    connection = sqlite3.connect(db_path)
    try:
        yield connection
    finally:
        connection.close()

db_path = "example.db"

with sqlite_connection(db_path) as connection:
    cursor = connection.cursor()
    cursor.execute("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)")
    cursor.execute("INSERT INTO users (name) VALUES (?)", ("Alice",))
    connection.commit()

with sqlite_connection(db_path) as connection:
    cursor = connection.cursor()
    cursor.execute("SELECT * FROM users")
    users = cursor.fetchall()
    print(users)
[(1, 'Alice')]
  • Mengakuisisi dan melepaskan kunci
    Manajer konteks juga dapat digunakan untuk mengelola kunci dalam lingkungan multi-threaded atau multi-process. Dalam contoh ini, kita menggunakan manajer konteks untuk menangani akuisisi dan pelepasan objek threading.Lock.
python
import threading
from contextlib import contextmanager

@contextmanager
def acquire_lock(lock):
    lock.acquire()
    try:
        yield
    finally:
        lock.release()

shared_data = 0
lock = threading.Lock()

def increment_shared_data():
    global shared_data
    with acquire_lock(lock):
        shared_data += 1
        print(f"Shared data incremented: {shared_data}")

threads = [threading.Thread(target=increment_shared_data) for _ in range(5)]

for thread in threads:
    thread.start()

for thread in threads:
    thread.join()

print(f"Final shared data value: {shared_data}")
Shared data incremented: 1
Shared data incremented: 2
Shared data incremented: 3
Shared data incremented: 4
Shared data incremented: 5
Final shared data value: 5

Penanganan Kesalahan dan Manajer Konteks

Dalam bab ini, saya membahas pentingnya penanganan kesalahan dalam manajer konteks dan bagaimana menangani pengecualian dengan efektif di dalamnya.

Pentingnya Penanganan Pengecualian

Penanganan pengecualian sangat penting saat bekerja dengan manajer konteks, karena memastikan bahwa resource dikelola dengan benar, bahkan di hadapan kesalahan atau pengecualian yang tidak terduga. Penanganan kesalahan yang tepat dapat membantu mencegah kebocoran resource, korupsi data, dan kerusakan aplikasi. Menggunakan manajer konteks dalam kombinasi dengan blok try-except dapat sangat meningkatkan keandalan dan kemudahan pemeliharaan kode Anda.

Menggabungkan Manajer Konteks dengan Blok try-except

Menggunakan blok try-except dalam manajer konteks memastikan bahwa pengecualian apa pun yang muncul di dalam blok yang dikelola ditangani dengan tepat. Ini memungkinkan manajer konteks untuk melepaskan resource dengan benar dan melakukan pembersihan yang diperlukan sebelum program melanjutkan.

Berikut ini contoh penggunaan blok try-except dalam manajer konteks:

python
from contextlib import contextmanager

@contextmanager
def managed_resource():
    print("Acquiring resource")
    resource = "Resource acquired"
    try:
        yield resource
    except Exception as e:
        print(f"Exception occurred: {e}")
        raise
    finally:
        print("Releasing resource")
        resource = None

with managed_resource() as res:
    print(res)
    raise ValueError("An error occurred")

Ketika kode ini dijalankan, Anda akan melihat output berikut:

Acquiring resource
Resource acquired
Exception occurred: An error occurred
Releasing resource
Traceback (most recent call last):
  ...
ValueError: An error occurred

Seperti yang dapat Anda lihat, pengecualian ditangani oleh manajer konteks, dan resource dilepaskan sebelum pengecualian dipropagasikan.

Dengan menggabungkan blok try-except dalam manajer konteks Anda, Anda dapat memastikan bahwa kode Anda tahan terhadap pengecualian yang tidak terduga dan bahwa resource dikelola dan dilepaskan dengan benar.

Referensi

https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!