आप शायद पहले से with स्टेटमेंट से परिचित होंगे, जो Python में संसाधनों को संभालने का संक्षिप्त तरीका है। लेकिन क्या आपने कभी सोचा है कि यह परदे के पीछे कैसे काम करता है? दरअसल, with कीवर्ड की शक्ति context managers से आती है।
Context managers Python का एक बुनियादी डिजाइन पैटर्न हैं जो संसाधन प्रबंधन के लिए एक संरचित तरीका देते हैं। ये सुनिश्चित करते हैं कि संसाधन प्राप्त किए जाएँ, सही तरीके से उपयोग हों, और अंत में—चाहे त्रुटि या अपवाद ही क्यों न हो—रिलीज़ या साफ कर दिए जाएँ।
यह खास तौर पर तब महत्वपूर्ण होता है जब आप फाइलों, नेटवर्क कनेक्शनों, या डेटाबेस हैंडल्स जैसे संसाधनों से निपटते हैं। Context managers का उपयोग करके, हम साफ-सुथरा और अधिक भरोसेमंद कोड लिख सकते हैं और फाइल बंद करना या लॉक रिलीज़ करना भूल जाने की चिंता से मुक्त हो सकते हैं।
इस ट्यूटोरियल में, हम Python के डिफ़ॉल्ट context managers से आगे बढ़कर अपने खुद के लिखना सीखेंगे।
Python में Context Managers को समझना
अंदरूनी तौर पर, context managers ऐसे ऑब्जेक्ट होते हैं जो दो विशेष मेथड्स परिभाषित करते हैं: __enter__ और __exit__। __enter__ मेथड तब कॉल होता है जब आप with ब्लॉक में प्रवेश करते हैं, और उसका रिटर्न मान उस ब्लॉक के भीतर एक वेरिएबल को असाइन हो जाता है। दूसरी ओर, __exit__ मेथड तब कॉल होता है जब with ब्लॉक से बाहर निकलते हैं—चाहे वह सामान्य रूप से समाप्त हो या किसी अपवाद के साथ।
यह संरचना उचित संसाधन हैंडलिंग सुनिश्चित करती है। इसे बेहतर समझने के लिए Python के कुछ बिल्ट-इन context managers देखें:
withopen('file.txt','r')asfile:
data =file.read()संचालित द्वारा
यहाँ, open('file.txt', 'r') context manager की तरह काम करता है। जब आप with ब्लॉक में प्रवेश करते हैं, तो फाइल ऑब्जेक्ट का enter मेथड कॉल होता है, जो फाइल खोलता है और उसे file वेरिएबल को असाइन कर देता है। फिर आप file.read() का उपयोग करके फाइल की सामग्री एक्सेस कर सकते हैं।
इसके बाद, with ब्लॉक से बाहर निकलते समय फाइल ऑब्जेक्ट का __exit__ मेथड कॉल होना सुनिश्चित होता है, भले ही कोई अपवाद हो। यह मेथड फाइल बंद करने का ध्यान रखता है, ताकि खुले फाइल हैंडल्स इधर-उधर न छूट जाएँ।
2. थ्रेड लॉकिंग
फाइलों से आगे बढ़कर, context managers को threading.Lock() का उपयोग कर थ्रेड सिंक्रोनाइज़ेशन के लिए भी इस्तेमाल किया जा सकता है:
import threading
lock = threading.Lock()with lock:# Critical sectionprint("This code is executed under lock protection.")संचालित द्वारा
यहाँ, lock एक threading.Lock ऑब्जेक्ट है, जो एक और context manager है। जब आप with ब्लॉक में प्रवेश करते हैं, तो __enter__ मेथड लॉक को acquire करता है, जिससे एक समय में केवल एक थ्रेड ही क्रिटिकल सेक्शन चला सके। अंत में, with ब्लॉक से बाहर निकलते समय __exit__ मेथड लॉक को रिलीज़ कर देता है, जिससे अन्य थ्रेड आगे बढ़ सकें।
3. डेटाबेस कनेक्शन्स
इसी तरह, context managers डेटाबेस कनेक्शनों को भी मैनेज कर सकते हैं:
import sqlite3
with sqlite3.connect('database.db')as connection:
cursor = connection.cursor()
cursor.execute("SELECT * FROM table")
rows = cursor.fetchall()संचालित द्वारा
sqlite3.connect('database.db') कॉल एक context manager है। with ब्लॉक में प्रवेश करते ही डेटाबेस से कनेक्शन स्थापित होता है और connection को असाइन हो जाता है। फिर आप cursor की मदद से डेटाबेस के साथ इंटरैक्ट कर सकते हैं। with ब्लॉक से बाहर निकलते समय __exit__ मेथड कनेक्शन को बंद करना सुनिश्चित करता है, जिससे संसाधन लीक न हों।
4. नेटवर्क सॉकेट्स
Context managers नेटवर्क संचार को भी संभाल सकते हैं:
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM)as s:
s.connect(('localhost',8080))
s.sendall(b'Hello, world')
data = s.recv(1024)संचालित द्वारा
यहाँ, socket.socket(socket.AF_INET, socket.SOCK_STREAM) एक सॉकेट ऑब्जेक्ट बनाता है जो context manager की तरह काम करता है। __enter__ मेथड सॉकेट बनाता है, और with ब्लॉक के भीतर आप कनेक्ट कर सकते हैं, डेटा भेज सकते हैं और प्राप्त कर सकते हैं। __exit__ मेथड सुनिश्चित करता है कि काम पूरा होने पर सॉकेट सही तरीके से बंद हो जाए।
5. डायरेक्टरी स्कैनिंग
इस बार, os.scandir('.') डायरेक्टरी एंट्रीज़ पर इटरेट करने का तरीका देता है:
with os.scandir('.')as entries:for entry in entries:print(entry.name)संचालित द्वारा
os.scandir('.') यहाँ context manager की तरह काम करता है। __enter__ मेथड डायरेक्टरी स्कैन खोलता है, और आप with ब्लॉक के भीतर एंट्रीज़ पर इटरेट कर सकते हैं। __exit__ मेथड बाहर निकलते समय स्कैन को साफ कर देता है।
जैसा कि आप देख सकते हैं, context managers द्वारा संचालित with स्टेटमेंट संसाधनों के आबंटन और विमोचन को स्वतः संभालकर प्रबंधन को सरल बना देता है।
Python में कस्टम context managers लिखना
अब, आइए देखें कि संसाधन प्रबंधन पर सूक्ष्म नियंत्रण पाने के लिए आप अपने कस्टम मैनेजर्स कैसे लिख सकते हैं।
कस्टम context managers लिखने के दो मुख्य तरीके हैं: क्लास-आधारित और फ़ंक्शन-आधारित।
क्लास-आधारित तरीका
क्लास-आधारित तरीका context managers लिखने का सबसे संरचित और लचीला तरीका है। यहाँ, आप एक क्लास परिभाषित करते हैं जो विशेष मेथड्स __enter__ और __exit__ को इम्प्लिमेंट करता है।
आइए एक Timer क्लास का उदाहरण देखें जो निष्पादन समय मापता है:
import time
classTimer:def__enter__(self):
self.start_time = time.time()return self
def__exit__(self, exc_type, exc_value, traceback):
self.end_time = time.time()
elapsed_time = self.end_time - self.start_time
print(f"Elapsed time: {elapsed_time} seconds")# Example usageif __name__ =="__main__":with Timer()as timer:# Code block to measure the execution time
time.sleep(2)# Simulate some time-consuming operation
Elapsed time:2.002082347869873 seconds
संचालित द्वारा
यहाँ, Timer क्लास with ब्लॉक में प्रवेश करते समय __enter__ मेथड में प्रारंभ समय कैप्चर करता है। यह self लौटाता है ताकि ब्लॉक के भीतर ऑब्जेक्ट की पहुँच बनी रहे। with ब्लॉक से बाहर निकलते समय __exit__ मेथड बीता हुआ समय गणना कर उसे प्रिंट करता है।
फ़ंक्शन-आधारित तरीका
यदि आप अधिक संक्षिप्त तरीका पसंद करते हैं—संभवतः लचीलेपन की कुछ कीमत पर—तो फ़ंक्शन-आधारित तरीका अच्छा विकल्प हो सकता है। इसमें contextlib मॉड्यूल के contextmanager डेकोरेटर का उपयोग कर किसी भी फ़ंक्शन को context manager में बदला जाता है।
आइए देखें यह कैसे काम करता है:
import time
from contextlib import contextmanager
@contextmanagerdeftimer():
start_time = time.time()yield
end_time = time.time()
elapsed_time = end_time - start_time
print(f"Elapsed time: {elapsed_time} seconds")# Example usageif __name__ =="__main__":with timer():
time.sleep(2)
Elapsed time:2.0020740032196045 seconds
संचालित द्वारा
@contextmanager डेकोरेटर timer फ़ंक्शन को context manager में बदल देता है। फ़ंक्शन के अंदर start_time कैप्चर होता है, और yield स्टेटमेंट निष्पादन रोक देता है ताकि with ब्लॉक के भीतर का कोड चल सके।
अंत में, __exit__ जैसी कार्यक्षमता अंत समय कैप्चर कर बीता हुआ समय प्रिंट करके हासिल की जाती है।
मूल रूप से, आप yield से पहले __enter__ की लॉजिक लिखते हैं और उसके बाद __exit__ की। दोनों तरीके एक ही परिणाम देते हैं; चुनाव आपके संरचना और पठनीयता के प्रति झुकाव पर निर्भर करता है।
Context Managers के व्यावहारिक उदाहरण
अब जब आप Python में कस्टम context managers लिखना समझ चुके हैं, तो आइए कुछ व्यावहारिक उदाहरण देखें जहाँ ये बेहद उपयोगी हो सकते हैं।
फ़ाइल ऑपरेशन्स का प्रबंधन
फाइल ऑपरेशन्स कई अनुप्रयोगों में आम कार्य हैं। फाइलों को पढ़ना या लिखना—दोनों में उचित प्रबंधन डेटा की अखंडता और संसाधन दक्षता सुनिश्चित करता है। मान लें कि हम कस्टम context manager का उपयोग करके किसी फाइल में टेक्स्ट लिखना चाहते हैं।
इस उदाहरण में, हम एक FileManager क्लास परिभाषित करते हैं जो Python के open फ़ंक्शन की तरह फाइल ऑपरेशन्स संभालता है। आइए देखें प्रत्येक मेथड क्या करता है:
__init__(self, filename, mode): यह क्लास का कन्स्ट्रक्टर है। यह दिए गए filename और mode के साथ FileManager ऑब्जेक्ट को इनिशियलाइज़ करता है, जो यह निर्दिष्ट करते हैं कि कौन सी फाइल और किस मोड (जैसे, पढ़ना, लिखना, जोड़ना) में खोली जाए।
__enter__(self): यह with ब्लॉक में प्रवेश करते ही कॉल होता है। यह filename और mode के अनुसार फाइल खोलता है। खोला गया फाइल ऑब्जेक्ट self.file को असाइन होता है और with ब्लॉक के भीतर उपयोग के लिए रिटर्न किया जाता है।
__exit__(self, exc_type, exc_value, traceback): यह with ब्लॉक से बाहर निकलते समय—चाहे अपवाद हुआ हो या नहीं—कॉल होता है। यदि self.fileNone नहीं है तो self.file.close() कॉल कर फाइल सही तरह से बंद करना सुनिश्चित करता है। इससे संसाधन लीक रुकते हैं और उचित क्लीनअप होता है।
यदि आप ऊपर का कोड चलाने के बाद example.txt की सामग्री देखें, तो लिखा हुआ टेक्स्ट दिखेगा:
बेशक, FileManager क्लास का लाभ यह है कि आप फाइलों के साथ काम करने के लिए कोई भी कस्टम लॉजिक इम्प्लिमेंट कर सकते हैं। उदाहरण के लिए, आप इसे इस तरह संशोधित कर सकते हैं कि यह कौन-सी फाइलें खोली/बंद की गईं, इसका लॉग एक टेक्स्ट फाइल में रखे।
datetime मॉड्यूल टाइमस्टैम्प के लिए इम्पोर्ट किया गया है।
log_action मेथड फाइल की क्रियाओं को लॉग करने के लिए जोड़ा गया है।
log_filename पैरामीटर लॉग फाइल के नाम को निर्दिष्ट करता है; डिफ़ॉल्ट 'file_log.txt' है।
__enter__ और __exit__ के भीतर log_action मेथड से फाइलनाम और क्रिया (opened/closed) लॉग फाइल में जोड़ दी जाती है।
log_action में datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") का उपयोग "YYYY-MM-DD HH:MM:SS" प्रारूप का वर्तमान टाइमस्टैम्प पाने के लिए किया गया है।
टाइमस्टैम्प को फाइलनाम और क्रिया के साथ लॉग में शामिल किया जाता है।
अब, यदि हम file_log.txt की सामग्री प्रिंट करें, तो लॉग दिखेंगे:
यह फिर से sqlite3.connect फ़ंक्शन की नकल करता है, लेकिन इसमें कस्टम डेटाबेस मैनेजमेंट लॉजिक जोड़कर इसे और बेहतर बनाया जा सकता है। चलिए कुछ सैंपल फ़ंक्शन्स से जाँचते हैं कि मैनेजर काम कर रहा है या नहीं:
# Example usagedefcreate_table():with DatabaseConnection("example.db")as connection:
cursor = connection.cursor()
cursor.execute("""CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
username TEXT,
email TEXT)""")definsert_data(username, email):with DatabaseConnection("example.db")as connection:
cursor = connection.cursor()
cursor.execute("INSERT INTO users (username, email) VALUES (?, ?)",(username, email))
connection.commit()deffetch_data():with DatabaseConnection("example.db")as connection:
cursor = connection.cursor()
cursor.execute("SELECT * FROM users")return cursor.fetchall()if __name__ =="__main__":
create_table()
insert_data("john_doe","[email protected]")
insert_data("jane_doe","[email protected]")
users = fetch_data()print("Users in the database:")for user in users:print(user)
Users in the database:(1,'john_doe','[email protected]')(2,'jane_doe','[email protected]')(3,'john_doe','[email protected]')(4,'jane_doe','[email protected]')संचालित द्वारा
हम डेटाबेस ऑपरेशन्स को फ़ंक्शन्स में तोड़कर और अपने बनाए कस्टम मैनेजर का उपयोग करके कहीं अधिक संभालने योग्य कोड लिख सकते हैं।
Python में Context Managers से जुड़े उन्नत विषय
इस खंड में, हम Python में context managers से जुड़े उन्नत विषयों पर चर्चा करेंगे। इनमें एरर हैंडलिंग और context managers का nesting शामिल है।
एरर हैंडलिंग
एरर हैंडलिंग प्रोग्रामिंग का एक अनिवार्य पक्ष है, और Python के context managers संसाधन प्रबंधन कार्यों के भीतर त्रुटियों को सुविधाजनक ढंग से संभालने का तरीका देते हैं।
FileManager क्लास के उदाहरण में, __exit__ मेथड के भीतर एरर हैंडलिंग इम्प्लिमेंट की जा सकती है ताकि अपवाद आने पर भी सही क्लीनअप हो। उदाहरण के लिए, यदि फाइल में डेटा लिखते समय (with ब्लॉक के दौरान) कोई त्रुटि होती है, तो भी हम फाइल बंद करना सुनिश्चित करना चाहेंगे ताकि संसाधन लीक न हों। हम __exit__ मेथड को इस तरह संशोधित कर सकते हैं:
यहाँ, हम पहले self.file.close() के जरिए सही क्लीनअप सुनिश्चित करते हैं। फिर जाँचते हैं कि कोई अपवाद हुआ था या नहीं (exc_type is not None)। यदि हुआ था, तो क्या गड़बड़ हुई इस पर फीडबैक देने के लिए एक एरर संदेश प्रिंट करते हैं।
यहाँ:
exc_type अपवाद क्लास है, जैसे AttributeError और IndexError।
exc_value संदेश सहित अपवाद इंस्टेंस है।
traceback त्रुटि का पूर्ण traceback है।
आइए जानबूझकर गलत कोड के साथ FileManager क्लास चलाएँ:
with FileManager("example.txt","r")asfile:# Simulate a sample error
content =file.read()print(content[150])
An error occurred: string index out of rangeसंचालित द्वारा
तो, अपने कस्टम मैनेजर्स में अपवादों को संभालते समय कस्टम लॉजिक इम्प्लिमेंट करने के लिए, आप यह नमूना वर्कफ़्लो अपना सकते हैं:
def__exit__(self, exc_type, exc_value, traceback):# Perform cleanup...# Handle the exceptionifisinstance(exc_value, AttributeError):# Handle AttributeError hereprint(f"Exception message: {exc_value}")# Handle another exceptionelifisinstance(exc_value, AnotherError):...संचालित द्वारा
Context managers का nesting
Context managers का nesting आपको एक ही with स्टेटमेंट के भीतर एकाधिक संसाधनों को, प्रत्येक के अपने context manager के साथ, एक साथ मैनेज करने देता है। यह खास तौर पर तब उपयोगी है जब जटिल ऑपरेशन्स में कई संसाधन शामिल होते हैं। आइए अपने उदाहरणों में context managers को nest करना देखें।
मान लें कि हम एक फाइल खोलना और उसी संदर्भ में डेटाबेस ऑपरेशन्स करना चाहते हैं। मसलन, हम किसी CSV फाइल की सामग्री को डेटाबेस में पंक्तियों के रूप में डालना चाहते हैं। यह हम FileManager और DatabaseConnection context managers को एक ही with स्टेटमेंट में nest करके कर सकते हैं:
if __name__ =="__main__":with FileManager("example.txt","w")asfile, DatabaseConnection("example.db")as connection:...संचालित द्वारा
इस उदाहरण में, FileManager और DatabaseConnection context managers एक ही with स्टेटमेंट में nested हैं। इससे हम फाइल खोलने और डेटाबेस कनेक्शन स्थापित करने दोनों को एक साथ कर पाते हैं। इसके बाद के फाइल-लेखन और डेटाबेस ऑपरेशन्स इसी संयुक्त संदर्भ में किए जाते हैं।
एक बात ध्यान में रखें—कोड की पठनीयता। मैं सिफारिश करूँगा कि एक साथ चल रहे contexts की संख्या दो से अधिक न हो।
निष्कर्ष
Python में context managers with स्टेटमेंट के भीतर संसाधन प्रबंधन के लिए एक संरचित तरीका देते हैं, जो संसाधनों के उचित आबंटन और विमोचन को सुनिश्चित करता है।
इस ट्यूटोरियल में, हमने context managers की मूल बातें सीखीं, व्यावहारिक उदाहरण देखे, और एरर हैंडलिंग व nesting जैसे उन्नत विषयों पर चर्चा की। कस्टम context managers लिखने में महारत हासिल कर, आप अधिक साफ, अधिक भरोसेमंद कोड लिख सकते हैं, एरर हैंडलिंग सुधार सकते हैं, और संसाधनों का कुशलता से प्रबंधन कर सकते हैं।
कस्टम context managers लिखने का विषय “Advanced Python” श्रेणी के अंतर्गत आता है। अपनी क्षमताओं को और निखारने के लिए ये संबंधित संसाधन देखें:
मैं 2 से अधिक वर्षों के अनुभव वाला डेटा साइंस कंटेंट क्रिएटर हूँ और Medium पर सबसे बड़े फॉलोइंग्स में से एक रखता हूँ। मुझे एआई और एमएल पर विस्तार से लेख लिखना पसंद है, जिसमें हल्का-सा व्यंग्यात्मक अंदाज रहता है—क्योंकि कुछ तो करना पड़ता है ताकि वे कम उबाऊ लगें। मैंने 130 से अधिक लेख और एक DataCamp कोर्स तैयार किया है, और एक और बन रहा है। मेरा कंटेंट 50 लाख से अधिक लोगों ने देखा है, जिनमें से 20 हज़ार लोग Medium और LinkedIn पर फॉलोअर्स बन गए।
अपने प्रोग्रामिंग कौशल को बेहतर बनाएं। कोड को अनुकूलित करना, फ़ंक्शन और परीक्षण लिखना, और सर्वोत्तम-अभ्यास सॉफ़्टवेयर इंजीनियरिंग तकनीकों का उपयोग करना सीखें।
प्रेरणा
आप शायद पहले से
withस्टेटमेंट से परिचित होंगे, जो Python में संसाधनों को संभालने का संक्षिप्त तरीका है। लेकिन क्या आपने कभी सोचा है कि यह परदे के पीछे कैसे काम करता है? दरअसल,withकीवर्ड की शक्ति context managers से आती है।Context managers Python का एक बुनियादी डिजाइन पैटर्न हैं जो संसाधन प्रबंधन के लिए एक संरचित तरीका देते हैं। ये सुनिश्चित करते हैं कि संसाधन प्राप्त किए जाएँ, सही तरीके से उपयोग हों, और अंत में—चाहे त्रुटि या अपवाद ही क्यों न हो—रिलीज़ या साफ कर दिए जाएँ।
यह खास तौर पर तब महत्वपूर्ण होता है जब आप फाइलों, नेटवर्क कनेक्शनों, या डेटाबेस हैंडल्स जैसे संसाधनों से निपटते हैं। Context managers का उपयोग करके, हम साफ-सुथरा और अधिक भरोसेमंद कोड लिख सकते हैं और फाइल बंद करना या लॉक रिलीज़ करना भूल जाने की चिंता से मुक्त हो सकते हैं।
इस ट्यूटोरियल में, हम Python के डिफ़ॉल्ट context managers से आगे बढ़कर अपने खुद के लिखना सीखेंगे।
Python में Context Managers को समझना
अंदरूनी तौर पर, context managers ऐसे ऑब्जेक्ट होते हैं जो दो विशेष मेथड्स परिभाषित करते हैं:
__enter__और__exit__।__enter__मेथड तब कॉल होता है जब आप with ब्लॉक में प्रवेश करते हैं, और उसका रिटर्न मान उस ब्लॉक के भीतर एक वेरिएबल को असाइन हो जाता है। दूसरी ओर,__exit__मेथड तब कॉल होता है जबwithब्लॉक से बाहर निकलते हैं—चाहे वह सामान्य रूप से समाप्त हो या किसी अपवाद के साथ।यह संरचना उचित संसाधन हैंडलिंग सुनिश्चित करती है। इसे बेहतर समझने के लिए Python के कुछ बिल्ट-इन context managers देखें:
1. फ़ाइल प्रबंधन
फाइल खोलने का क्लासिक उदाहरण लें:
यहाँ,
open('file.txt', 'r')context manager की तरह काम करता है। जब आपwithब्लॉक में प्रवेश करते हैं, तो फाइल ऑब्जेक्ट का enter मेथड कॉल होता है, जो फाइल खोलता है और उसे file वेरिएबल को असाइन कर देता है। फिर आपfile.read()का उपयोग करके फाइल की सामग्री एक्सेस कर सकते हैं।इसके बाद,
withब्लॉक से बाहर निकलते समय फाइल ऑब्जेक्ट का__exit__मेथड कॉल होना सुनिश्चित होता है, भले ही कोई अपवाद हो। यह मेथड फाइल बंद करने का ध्यान रखता है, ताकि खुले फाइल हैंडल्स इधर-उधर न छूट जाएँ।2. थ्रेड लॉकिंग
फाइलों से आगे बढ़कर, context managers को
threading.Lock()का उपयोग कर थ्रेड सिंक्रोनाइज़ेशन के लिए भी इस्तेमाल किया जा सकता है:यहाँ,
lockएकthreading.Lockऑब्जेक्ट है, जो एक और context manager है। जब आपwithब्लॉक में प्रवेश करते हैं, तो__enter__मेथड लॉक को acquire करता है, जिससे एक समय में केवल एक थ्रेड ही क्रिटिकल सेक्शन चला सके। अंत में,withब्लॉक से बाहर निकलते समय__exit__मेथड लॉक को रिलीज़ कर देता है, जिससे अन्य थ्रेड आगे बढ़ सकें।3. डेटाबेस कनेक्शन्स
इसी तरह, context managers डेटाबेस कनेक्शनों को भी मैनेज कर सकते हैं:
sqlite3.connect('database.db')कॉल एक context manager है।withब्लॉक में प्रवेश करते ही डेटाबेस से कनेक्शन स्थापित होता है औरconnectionको असाइन हो जाता है। फिर आपcursorकी मदद से डेटाबेस के साथ इंटरैक्ट कर सकते हैं।withब्लॉक से बाहर निकलते समय__exit__मेथड कनेक्शन को बंद करना सुनिश्चित करता है, जिससे संसाधन लीक न हों।4. नेटवर्क सॉकेट्स
Context managers नेटवर्क संचार को भी संभाल सकते हैं:
यहाँ,
socket.socket(socket.AF_INET, socket.SOCK_STREAM)एक सॉकेट ऑब्जेक्ट बनाता है जो context manager की तरह काम करता है।__enter__मेथड सॉकेट बनाता है, औरwithब्लॉक के भीतर आप कनेक्ट कर सकते हैं, डेटा भेज सकते हैं और प्राप्त कर सकते हैं।__exit__मेथड सुनिश्चित करता है कि काम पूरा होने पर सॉकेट सही तरीके से बंद हो जाए।5. डायरेक्टरी स्कैनिंग
इस बार,
os.scandir('.')डायरेक्टरी एंट्रीज़ पर इटरेट करने का तरीका देता है:os.scandir('.')यहाँ context manager की तरह काम करता है।__enter__मेथड डायरेक्टरी स्कैन खोलता है, और आपwithब्लॉक के भीतर एंट्रीज़ पर इटरेट कर सकते हैं।__exit__मेथड बाहर निकलते समय स्कैन को साफ कर देता है।जैसा कि आप देख सकते हैं, context managers द्वारा संचालित
withस्टेटमेंट संसाधनों के आबंटन और विमोचन को स्वतः संभालकर प्रबंधन को सरल बना देता है।Python में कस्टम context managers लिखना
अब, आइए देखें कि संसाधन प्रबंधन पर सूक्ष्म नियंत्रण पाने के लिए आप अपने कस्टम मैनेजर्स कैसे लिख सकते हैं।
कस्टम context managers लिखने के दो मुख्य तरीके हैं: क्लास-आधारित और फ़ंक्शन-आधारित।
क्लास-आधारित तरीका
क्लास-आधारित तरीका context managers लिखने का सबसे संरचित और लचीला तरीका है। यहाँ, आप एक क्लास परिभाषित करते हैं जो विशेष मेथड्स
__enter__और__exit__को इम्प्लिमेंट करता है।आइए एक
Timerक्लास का उदाहरण देखें जो निष्पादन समय मापता है:यहाँ,
Timerक्लासwithब्लॉक में प्रवेश करते समय__enter__मेथड में प्रारंभ समय कैप्चर करता है। यहselfलौटाता है ताकि ब्लॉक के भीतर ऑब्जेक्ट की पहुँच बनी रहे।withब्लॉक से बाहर निकलते समय__exit__मेथड बीता हुआ समय गणना कर उसे प्रिंट करता है।फ़ंक्शन-आधारित तरीका
यदि आप अधिक संक्षिप्त तरीका पसंद करते हैं—संभवतः लचीलेपन की कुछ कीमत पर—तो फ़ंक्शन-आधारित तरीका अच्छा विकल्प हो सकता है। इसमें
contextlibमॉड्यूल केcontextmanagerडेकोरेटर का उपयोग कर किसी भी फ़ंक्शन को context manager में बदला जाता है।आइए देखें यह कैसे काम करता है:
@contextmanagerडेकोरेटरtimerफ़ंक्शन को context manager में बदल देता है। फ़ंक्शन के अंदरstart_timeकैप्चर होता है, औरyieldस्टेटमेंट निष्पादन रोक देता है ताकिwithब्लॉक के भीतर का कोड चल सके।अंत में,
__exit__जैसी कार्यक्षमता अंत समय कैप्चर कर बीता हुआ समय प्रिंट करके हासिल की जाती है।मूल रूप से, आप
yieldसे पहले__enter__की लॉजिक लिखते हैं और उसके बाद__exit__की। दोनों तरीके एक ही परिणाम देते हैं; चुनाव आपके संरचना और पठनीयता के प्रति झुकाव पर निर्भर करता है।Context Managers के व्यावहारिक उदाहरण
अब जब आप Python में कस्टम context managers लिखना समझ चुके हैं, तो आइए कुछ व्यावहारिक उदाहरण देखें जहाँ ये बेहद उपयोगी हो सकते हैं।
फ़ाइल ऑपरेशन्स का प्रबंधन
फाइल ऑपरेशन्स कई अनुप्रयोगों में आम कार्य हैं। फाइलों को पढ़ना या लिखना—दोनों में उचित प्रबंधन डेटा की अखंडता और संसाधन दक्षता सुनिश्चित करता है। मान लें कि हम कस्टम context manager का उपयोग करके किसी फाइल में टेक्स्ट लिखना चाहते हैं।
इस उदाहरण में, हम एक
FileManagerक्लास परिभाषित करते हैं जो Python केopenफ़ंक्शन की तरह फाइल ऑपरेशन्स संभालता है। आइए देखें प्रत्येक मेथड क्या करता है:__init__(self, filename, mode): यह क्लास का कन्स्ट्रक्टर है। यह दिए गए filename और mode के साथFileManagerऑब्जेक्ट को इनिशियलाइज़ करता है, जो यह निर्दिष्ट करते हैं कि कौन सी फाइल और किस मोड (जैसे, पढ़ना, लिखना, जोड़ना) में खोली जाए।__enter__(self): यहwithब्लॉक में प्रवेश करते ही कॉल होता है। यहfilenameऔरmodeके अनुसार फाइल खोलता है। खोला गया फाइल ऑब्जेक्टself.fileको असाइन होता है औरwithब्लॉक के भीतर उपयोग के लिए रिटर्न किया जाता है।__exit__(self, exc_type, exc_value, traceback): यहwithब्लॉक से बाहर निकलते समय—चाहे अपवाद हुआ हो या नहीं—कॉल होता है। यदिself.fileNoneनहीं है तोself.file.close()कॉल कर फाइल सही तरह से बंद करना सुनिश्चित करता है। इससे संसाधन लीक रुकते हैं और उचित क्लीनअप होता है।यदि आप ऊपर का कोड चलाने के बाद
example.txtकी सामग्री देखें, तो लिखा हुआ टेक्स्ट दिखेगा:बेशक,
FileManagerक्लास का लाभ यह है कि आप फाइलों के साथ काम करने के लिए कोई भी कस्टम लॉजिक इम्प्लिमेंट कर सकते हैं। उदाहरण के लिए, आप इसे इस तरह संशोधित कर सकते हैं कि यह कौन-सी फाइलें खोली/बंद की गईं, इसका लॉग एक टेक्स्ट फाइल में रखे।इस संशोधित संस्करण में:
datetimeमॉड्यूल टाइमस्टैम्प के लिए इम्पोर्ट किया गया है।log_actionमेथड फाइल की क्रियाओं को लॉग करने के लिए जोड़ा गया है।log_filenameपैरामीटर लॉग फाइल के नाम को निर्दिष्ट करता है; डिफ़ॉल्ट'file_log.txt'है।__enter__और__exit__के भीतरlog_actionमेथड से फाइलनाम और क्रिया (opened/closed) लॉग फाइल में जोड़ दी जाती है।log_actionमेंdatetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")का उपयोग"YYYY-MM-DD HH:MM:SS"प्रारूप का वर्तमान टाइमस्टैम्प पाने के लिए किया गया है।अब, यदि हम
file_log.txtकी सामग्री प्रिंट करें, तो लॉग दिखेंगे:एक और व्यावहारिक उपयोग-मामला जिसे हम कस्टम context manager के रूप में इम्प्लिमेंट कर सकते हैं, वह है SQLite डेटाबेस मैनेजमेंट टूल:
यह फिर से
sqlite3.connectफ़ंक्शन की नकल करता है, लेकिन इसमें कस्टम डेटाबेस मैनेजमेंट लॉजिक जोड़कर इसे और बेहतर बनाया जा सकता है। चलिए कुछ सैंपल फ़ंक्शन्स से जाँचते हैं कि मैनेजर काम कर रहा है या नहीं:हम डेटाबेस ऑपरेशन्स को फ़ंक्शन्स में तोड़कर और अपने बनाए कस्टम मैनेजर का उपयोग करके कहीं अधिक संभालने योग्य कोड लिख सकते हैं।
Python में Context Managers से जुड़े उन्नत विषय
इस खंड में, हम Python में context managers से जुड़े उन्नत विषयों पर चर्चा करेंगे। इनमें एरर हैंडलिंग और context managers का nesting शामिल है।
एरर हैंडलिंग
एरर हैंडलिंग प्रोग्रामिंग का एक अनिवार्य पक्ष है, और Python के context managers संसाधन प्रबंधन कार्यों के भीतर त्रुटियों को सुविधाजनक ढंग से संभालने का तरीका देते हैं।
FileManager क्लास के उदाहरण में,
__exit__मेथड के भीतर एरर हैंडलिंग इम्प्लिमेंट की जा सकती है ताकि अपवाद आने पर भी सही क्लीनअप हो। उदाहरण के लिए, यदि फाइल में डेटा लिखते समय (withब्लॉक के दौरान) कोई त्रुटि होती है, तो भी हम फाइल बंद करना सुनिश्चित करना चाहेंगे ताकि संसाधन लीक न हों। हम__exit__मेथड को इस तरह संशोधित कर सकते हैं:यहाँ, हम पहले
self.file.close()के जरिए सही क्लीनअप सुनिश्चित करते हैं। फिर जाँचते हैं कि कोई अपवाद हुआ था या नहीं(exc_type is not None)। यदि हुआ था, तो क्या गड़बड़ हुई इस पर फीडबैक देने के लिए एक एरर संदेश प्रिंट करते हैं।यहाँ:
exc_typeअपवाद क्लास है, जैसेAttributeErrorऔरIndexError।exc_valueसंदेश सहित अपवाद इंस्टेंस है।tracebackत्रुटि का पूर्ण traceback है।आइए जानबूझकर गलत कोड के साथ
FileManagerक्लास चलाएँ:तो, अपने कस्टम मैनेजर्स में अपवादों को संभालते समय कस्टम लॉजिक इम्प्लिमेंट करने के लिए, आप यह नमूना वर्कफ़्लो अपना सकते हैं:
Context managers का nesting
Context managers का nesting आपको एक ही
withस्टेटमेंट के भीतर एकाधिक संसाधनों को, प्रत्येक के अपने context manager के साथ, एक साथ मैनेज करने देता है। यह खास तौर पर तब उपयोगी है जब जटिल ऑपरेशन्स में कई संसाधन शामिल होते हैं। आइए अपने उदाहरणों में context managers को nest करना देखें।मान लें कि हम एक फाइल खोलना और उसी संदर्भ में डेटाबेस ऑपरेशन्स करना चाहते हैं। मसलन, हम किसी CSV फाइल की सामग्री को डेटाबेस में पंक्तियों के रूप में डालना चाहते हैं। यह हम
FileManagerऔरDatabaseConnectioncontext managers को एक हीwithस्टेटमेंट में nest करके कर सकते हैं:इस उदाहरण में, FileManager और DatabaseConnection context managers एक ही
withस्टेटमेंट में nested हैं। इससे हम फाइल खोलने और डेटाबेस कनेक्शन स्थापित करने दोनों को एक साथ कर पाते हैं। इसके बाद के फाइल-लेखन और डेटाबेस ऑपरेशन्स इसी संयुक्त संदर्भ में किए जाते हैं।एक बात ध्यान में रखें—कोड की पठनीयता। मैं सिफारिश करूँगा कि एक साथ चल रहे contexts की संख्या दो से अधिक न हो।
निष्कर्ष
Python में context managers
withस्टेटमेंट के भीतर संसाधन प्रबंधन के लिए एक संरचित तरीका देते हैं, जो संसाधनों के उचित आबंटन और विमोचन को सुनिश्चित करता है।इस ट्यूटोरियल में, हमने context managers की मूल बातें सीखीं, व्यावहारिक उदाहरण देखे, और एरर हैंडलिंग व nesting जैसे उन्नत विषयों पर चर्चा की। कस्टम context managers लिखने में महारत हासिल कर, आप अधिक साफ, अधिक भरोसेमंद कोड लिख सकते हैं, एरर हैंडलिंग सुधार सकते हैं, और संसाधनों का कुशलता से प्रबंधन कर सकते हैं।
कस्टम context managers लिखने का विषय “Advanced Python” श्रेणी के अंतर्गत आता है। अपनी क्षमताओं को और निखारने के लिए ये संबंधित संसाधन देखें: