পাইথনের স্ট্যান্ডার্ড লাইব্রেরির contextlib মডিউল ContextManager ক্লাস সংজ্ঞায়িত করে যার অবজেক্ট একটি প্রোগ্রামের মধ্যে রিসোর্স সঠিকভাবে ম্যানেজ করে। পাইথনে with কীওয়ার্ড আছে যা কনটেক্সট ম্যানেজারের সাথে কাজ করে। ফাইল অবজেক্ট (যা বিল্ট-ইন open() ফাংশন দ্বারা রিটার্ন করা হয়) ContextManager API সাপোর্ট করে। তাই আমরা ফাইল নিয়ে কাজ করার সময় with কীওয়ার্ড ব্যবহার করা দেখি।
নিচের কোড ব্লক একটি ফাইল খোলে এবং সেটিতে কিছু ডেটা লিখে। অপারেশন শেষ হলে ফাইলটি বন্ধ করা হয়, না হলে ফাইল ডেসক্রিপ্টর লিক হতে পারে যাতে ফাইল করপশন হয়।
f = open("file.txt", "w")
f.write("hello world")
f.close()
তবে একই ফাইল অপারেশন ফাইলের কনটেক্সট ম্যানেজার ক্যাপাবিলিটি ব্যবহার করে নিচের সিনট্যাক্সে করা যায়:
with open("file.txt", "w") as f:
f.write("hello world")
print("file is closed")
উল্লিখিত kimi, ফাইল অবজেক্ট ContextManager ইমপ্লিমেন্ট করে। এটি with কীওয়ার্ড দ্বারা সক্ষম করা হয়। with ব্লকতে ফাইল অবজেক্টের জন্য প্রসেস করা স্টেটমেন্ট থাকে। যতক্ষণ with ব্লক শেষ হয়, ফাইল অবজেক্টটি অটোমেটিক্যালি বন্ধ হয়ে যায় (close() মেথড স্পষ্টভাবে কল করতে হয় না)। with ব্লকে অধীন যেকোনো অবজেক্ট শুধু ব্লকের ভিতরে সক্রিয় থাকে এবং এর শেষে তাৎক্ষণিকভাবে ডিসপোজ করা হয়।
ContextManager ক্লাসের দুটি জরুরি মেথড আছে __enter__() এবং __exit__():
- __enter__() − with ব্লক শুরু হলে কল করা হয়। এটি ইঙ্গিত দেয় যে প্রোগ্রাম এই অবজেক্টের সাথে সম্পর্কিত রানটাইম কনটেক্সটে প্রবেশ করেছে।
- __exit__() − with ব্লক শেষ হলে কল করা হয়। এটি ইঙ্গিত দেয় যে প্রোগ্রাম এই অবজেক্টের সাথে সম্পর্কিত রানটাইম কনটেক্সট থেকে বাইরে যাচ্ছে।
ফাইল অবজেক্টটিও এই দুটি মেথড 갖고 있음을 নিচের ইন্টারপ্রেটার সেশন দ্বারা নিশ্চিত করা যায়:
>>> f = open("file.txt", "w")
>>> f.__enter__()
<_io.TextIOWrapper name='file.txt' mode='w' encoding='cp1252'>
>>> f.write("hello world")
11
>>> f.__exit__()
>>> f.write("hello world")
Traceback (most recent call last):
File "", line 1, in
f.write("hello world")
ValueError: I/O operation on closed file.
যখন __exit__() মেথড কল করা হয়, ফাইলটি বন্ধ হয়ে যায়। তাই ValueError দেখায় কারণ আমরা বন্ধ ফাইলে ডেটা লিখতে চেষ্টা করলাম।
নিচে contextManager-এর একটি আরও জেনারেলাইজড ব্যবহার দেওয়া হলো। প্রথমে __enter__() এবং __exit__() মেথডসহ একটি ক্লাস ডিফাইন করি এবং with স্টেটমেন্ট ব্যবহার করে এর অবজেক্টের জন্য কনটেক্সট ম্যানেজার সক্ষম করি।
import contextlib
class WithExample:
def __init__(self):
print("object initialized")
def __enter__(self):
print("entered context")
def __exit__(self, *args):
print("exited context")
with WithExample() as w:
print('this is a contextlib example')
print('used by with statement')
print('end of with block')
আউটপুট দেখায় যে with ব্লক শুরু होते ही __enter__() মেথড এক্সিকিউট হয়। ব্লকের ভিতরের স্টেটমেন্টগুলো প্রসেস হয়। ব্লক শেষ হলে __exit__() মেথডও অটোমেটিক্যালি কল হয়।
object initialized entered context this is a contextlib example used by with statement exited context end of with block
contextlib মডিউলে @contextmanager ডেকোরেটর আছে যার সাহায্যে আমরা একটি জেনারেটর-ভিত্তিক ফ্যাক্টরি ফাংশন লিখতে পারি যা অটোমেটিক্যালি with স্টেটমেন্ট সাপোর্ট করে। ফাইল অবজেক্টের কনটেক্সট ম্যানেজমেন্ট ডেকোরেটরসহ নিচের মত:
from contextlib import contextmanager
@contextmanager
def openfile(name):
try:
f = open(name, 'w')
yield f
finally:
f.close()
with openfile('file.txt') as f:
f.write('hello world')
print('file is closed')
ContextManager এইভাবে পাইথনের একটি খুবই উপকারী বৈশিষ্ট্য প্রোগ্রামে রিসোর্স কার্যকরভাবে ম্যানেজ করার জন্য।