Python Language
संदर्भ प्रबंधक ("कथन के साथ")
खोज…
परिचय
जबकि पायथन के संदर्भ प्रबंधक व्यापक रूप से उपयोग किए जाते हैं, कुछ लोग उनके उपयोग के पीछे के उद्देश्य को समझते हैं। आमतौर पर फ़ाइलों को पढ़ने और लिखने के साथ उपयोग किए जाने वाले ये कथन सिस्टम मेमोरी को संरक्षित करने में एप्लिकेशन की सहायता करते हैं और कुछ प्रक्रियाओं के लिए केवल विशिष्ट संसाधनों का उपयोग करके संसाधन प्रबंधन में सुधार करते हैं। यह विषय पायथन के संदर्भ प्रबंधकों के उपयोग की व्याख्या और प्रदर्शन करता है।
वाक्य - विन्यास
- "Reference_manager" ("उपनाम" के रूप में) (, "reference_manager" ("उपनाम") के रूप में?):?
टिप्पणियों
संदर्भ प्रबंधक पीईपी 343 में परिभाषित किए गए हैं। वे try ... finally
तुलना में संसाधन प्रबंधन के लिए अधिक रसीला तंत्र के रूप में उपयोग किए जाने का इरादा रखते हैं try ... finally
निर्माण करते हैं। औपचारिक परिभाषा इस प्रकार है।
इस PEP में, संदर्भ प्रबंधक
__enter__()
और__exit__()
विधियां प्रदान करते हैं जो कि प्रवेश के साथ और कथन के शरीर से बाहर निकलने पर आह्वान किया जाता है।
यह तो परिभाषित करने के लिए पर चला जाता है with
इस प्रकार के बयान।
with EXPR as VAR: BLOCK
उपरोक्त कथन का अनुवाद है:
mgr = (EXPR) exit = type(mgr).__exit__ # Not calling it yet value = type(mgr).__enter__(mgr) exc = True try: try: VAR = value # Only if "as VAR" is present BLOCK except: # The exceptional case is handled here exc = False if not exit(mgr, *sys.exc_info()): raise # The exception is swallowed if exit() returns true finally: # The normal and non-local-goto cases are handled here if exc: exit(mgr, None, None, None)
संदर्भ प्रबंधकों का परिचय और कथन के साथ
एक संदर्भ प्रबंधक एक वस्तु है जिसे एक संदर्भ (कोड का एक ब्लॉक) शुरू होने और समाप्त होने पर अधिसूचित किया जाता है । आप आमतौर पर कथन के with
एक का उपयोग करते हैं। यह ध्यान देने योग्य है।
उदाहरण के लिए, फ़ाइल ऑब्जेक्ट संदर्भ प्रबंधक हैं। जब कोई संदर्भ समाप्त होता है, तो फ़ाइल ऑब्जेक्ट स्वचालित रूप से बंद हो जाता है:
open_file = open(filename)
with open_file:
file_contents = open_file.read()
# the open_file object has automatically been closed.
ऊपर दिए गए उदाहरण को आमतौर पर कीवर्ड के as
उपयोग करके सरल किया as
:
with open(filename) as open_file:
file_contents = open_file.read()
# the open_file object has automatically been closed.
कुछ भी जो ब्लॉक के निष्पादन को समाप्त करता है, संदर्भ प्रबंधक के निकास विधि को कहा जाता है। इसमें अपवाद शामिल हैं, और तब उपयोगी हो सकता है जब कोई त्रुटि आपको एक खुली फ़ाइल या कनेक्शन से समय से पहले निकलने का कारण बनती है। फ़ाइलों / कनेक्शनों को ठीक से बंद किए बिना स्क्रिप्ट से बाहर निकलना एक बुरा विचार है, जिससे डेटा हानि या अन्य समस्याएं हो सकती हैं। एक संदर्भ प्रबंधक का उपयोग करके आप यह सुनिश्चित कर सकते हैं कि इस तरह से नुकसान या हानि को रोकने के लिए हमेशा सावधानी बरती जाती है। पायथन 2.5 में यह फीचर जोड़ा गया था।
किसी लक्ष्य को सौंपना
कई संदर्भ प्रबंधक दर्ज किए जाने पर एक वस्तु लौटाते हैं। आप उस वस्तु को नए नाम के with
स्टेटमेंट में असाइन कर सकते हैं।
उदाहरण के लिए, एक में एक डेटाबेस कनेक्शन का उपयोग कर with
बयान आप एक कर्सर वस्तु दे सकता है:
with database_connection as cursor:
cursor.execute(sql_query)
फ़ाइल ऑब्जेक्ट्स स्वयं लौटते हैं, इससे फ़ाइल ऑब्जेक्ट को खोलना और इसे एक संदर्भ में संदर्भ प्रबंधक के रूप में उपयोग करना संभव हो जाता है:
with open(filename) as open_file:
file_contents = open_file.read()
अपना खुद का संदर्भ प्रबंधक लिखना
एक संदर्भ प्रबंधक कोई भी वस्तु है जो दो जादू विधियों __enter__()
और __exit__()
को लागू करता है (हालांकि यह अन्य तरीकों को भी लागू कर सकता है):
class AContextManager():
def __enter__(self):
print("Entered")
# optionally return an object
return "A-instance"
def __exit__(self, exc_type, exc_value, traceback):
print("Exited" + (" (with an exception)" if exc_type else ""))
# return True if you want to suppress the exception
यदि संदर्भ अपवाद से बाहर निकलता है, तो उस अपवाद के बारे में जानकारी ट्रिपल exc_type
, exc_value
, traceback
रूप में पारित हो जाएगी (ये वही वैरिएबल हैं जैसे कि sys.exc_info()
फ़ंक्शन द्वारा लौटाए गए हैं)। यदि संदर्भ सामान्य रूप से बाहर निकलता है, तो इन तीनों में से None
तर्क None
होगा।
यदि कोई अपवाद होता है और __exit__
विधि से पारित किया जाता है, तो अपवाद को दबाने के लिए विधि True
तरीके से वापस आ सकती है, या अपवाद __exit__
फ़ंक्शन के अंत में फिर से उठाया जाएगा।
with AContextManager() as a:
print("a is %r" % a)
# Entered
# a is 'A-instance'
# Exited
with AContextManager() as a:
print("a is %d" % a)
# Entered
# Exited (with an exception)
# Traceback (most recent call last):
# File "<stdin>", line 2, in <module>
# TypeError: %d format: a number is required, not str
ध्यान दें कि दूसरे उदाहरण में भले ही एक बयान के साथ शरीर के बीच में अपवाद हो, __exit__
हैंडलर को अभी भी निष्पादित किया जाता है, इससे पहले कि अपवाद बाहरी दायरे में फैलता है।
यदि आपको केवल __exit__
विधि की आवश्यकता है, तो आप संदर्भ प्रबंधक का उदाहरण वापस कर सकते हैं:
class MyContextManager:
def __enter__(self):
return self
def __exit__(self):
print('something')
जनरेटर सिंटैक्स का उपयोग करके अपना स्वयं का संदर्भ लिखना
यह भी संभव है करने के लिए जनरेटर वाक्य रचना धन्यवाद का उपयोग कर एक संदर्भ प्रबंधक लिखने के contextlib.contextmanager
डेकोरेटर:
import contextlib
@contextlib.contextmanager
def context_manager(num):
print('Enter')
yield num + 1
print('Exit')
with context_manager(2) as cm:
# the following instructions are run when the 'yield' point of the context
# manager is reached.
# 'cm' will have the value that was yielded
print('Right in the middle with cm = {}'.format(cm))
पैदा करता है:
Enter
Right in the middle with cm = 3
Exit
डेकोरेटर जनरेटर को एक में परिवर्तित करके एक संदर्भ प्रबंधक लिखने का कार्य सरल करता है। उपज अभिव्यक्ति से पहले सब कुछ __enter__
विधि बन जाता है, उपज का मूल्य जनरेटर द्वारा लौटाया गया मान बन जाता है (जो कि कथन के साथ एक चर के लिए बाध्य हो सकता है), और उपज अभिव्यक्ति के बाद सब कुछ __exit__
विधि बन जाता है।
एक अपवाद की जरूरत संदर्भ प्रबंधक द्वारा नियंत्रित किया जा करने के लिए करते हैं, तो एक try..except..finally
-block जनरेटर में लिखा जा सकता है और किसी भी अपवाद में उठाया with
-block इस अपवाद ब्लॉक द्वारा नियंत्रित किया जाएगा।
@contextlib.contextmanager
def error_handling_context_manager(num):
print("Enter")
try:
yield num + 1
except ZeroDivisionError:
print("Caught error")
finally:
print("Cleaning up")
print("Exit")
with error_handling_context_manager(-1) as cm:
print("Dividing by cm = {}".format(cm))
print(2 / cm)
यह उत्पादन करता है:
Enter
Dividing by cm = 0
Caught error
Cleaning up
Exit
एकाधिक संदर्भ प्रबंधक
आप एक ही समय में कई सामग्री प्रबंधक खोल सकते हैं:
with open(input_path) as input_file, open(output_path, 'w') as output_file:
# do something with both files.
# e.g. copy the contents of input_file into output_file
for line in input_file:
output_file.write(line + '\n')
यह घोंसले के शिकार प्रबंधकों के रूप में एक ही प्रभाव है:
with open(input_path) as input_file:
with open(output_path, 'w') as output_file:
for line in input_file:
output_file.write(line + '\n')
संसाधन प्रबंधित करें
class File():
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
self.open_file = open(self.filename, self.mode)
return self.open_file
def __exit__(self, *args):
self.open_file.close()
__init__()
विधि ऑब्जेक्ट सेट करती है, इस मामले में फ़ाइल का नाम और फ़ाइल खोलने के लिए मोड सेट करना है। __enter__()
फ़ाइल को खोलता है और लौटाता है और __exit__()
बस इसे बंद कर देता है।
इन जादू विधियों (का उपयोग करते हुए __enter__
, __exit__
) आप वस्तुओं जो आसानी से इस्तेमाल किया जा सकता लागू करने के लिए अनुमति देता है with
बयान के साथ।
फ़ाइल वर्ग का उपयोग करें:
for _ in range(10000):
with File('foo.txt', 'w') as f:
f.write('foo')