Python Language
कचरा इकठा करना
खोज…
टिप्पणियों
इसके मूल में, पायथन का कचरा संग्राहक (3.5 के रूप में) एक साधारण संदर्भ गणना कार्यान्वयन है। हर बार जब आप किसी वस्तु का संदर्भ बनाते हैं (उदाहरण के लिए, a = myobject
) तो उस वस्तु (myobject) पर संदर्भ संख्या बढ़ाई जाती है। हर बार जब कोई संदर्भ हटा दिया जाता है, तो संदर्भ संख्या को घटा दिया जाता है, और एक बार जब संदर्भ संख्या 0
तक पहुंच जाती है, तो हम जानते हैं कि कुछ भी उस वस्तु का संदर्भ नहीं रखता है और हम इसे निपटा सकते हैं!
पायथन मेमोरी प्रबंधन कैसे काम करता है इसके बारे में एक आम गलतफहमी यह है कि del
कीवर्ड ऑब्जेक्ट मेमोरी को मुक्त करता है। यह सच नहीं है। वास्तव में क्या होता है कि del
कीवर्ड केवल वस्तुओं को रिफरेक्ट करता है, जिसका अर्थ है कि यदि आप रिफंड के लिए पर्याप्त बार कॉल करते हैं तो शून्य वस्तु तक पहुंचाया जा सकता है (भले ही वास्तव में आपके कोड में कहीं और उपलब्ध वस्तु के संदर्भ अभी भी हों। )।
पायथन एग्रेसिवली ऑब्जेक्ट्स को बनाता या साफ करता है पहली बार इसकी आवश्यकता होती है यदि मैं असाइनमेंट ए = ऑब्जेक्ट () करता हूं, तो उस समय ऑब्जेक्ट के लिए मेमोरी आवंटित की जाती है (cpython कभी-कभी कुछ प्रकार की ऑब्जेक्ट का पुन: उपयोग करेगा, जैसे हुड के तहत सूची।) लेकिन ज्यादातर यह एक मुफ्त वस्तु पूल नहीं रखता है और जब आपको इसकी आवश्यकता होगी तो आवंटन करेगा)। इसी तरह, जैसे ही रिफंड को 0 से घटाया जाता है, जीसी उसे साफ कर देता है।
पीढ़ीगत कचरा संग्रह
1960 में जॉन मैकार्थी ने कचरा संग्रह को फिर से भरने में एक घातक दोष का पता लगाया जब उन्होंने लिस्प द्वारा उपयोग किए जाने वाले रिफेकिंग एल्गोरिथ्म को लागू किया: यदि दो वस्तुएं एक चक्रीय संदर्भ में एक दूसरे को संदर्भित करती हैं तो क्या होता है? आप कभी भी उन दो वस्तुओं को कैसे इकट्ठा कर सकते हैं, भले ही उनके लिए कोई बाहरी संदर्भ न हो अगर वे हमेशा एक-दूसरे को संदर्भित करेंगे? यह समस्या किसी भी चक्रीय डेटा संरचना तक फैली हुई है, जैसे कि रिंग बफ़र्स या किसी भी लगातार लिंक की गई सूची में दो लगातार प्रविष्टियाँ। पायथन एक और कचरा संग्रह एल्गोरिथ्म पर थोड़ा दिलचस्प मोड़ का उपयोग करके इस समस्या को ठीक करने का प्रयास करता है जिसे जनरेशनल कचरा संग्रह कहा जाता है।
संक्षेप में, जब भी आप पाइथन में कोई वस्तु बनाते हैं तो यह एक दोगुनी लिंक्ड सूची के अंत में जुड़ जाता है। इस सूची के माध्यम से, पायथन लूप्स की जाँच करता है कि सूची में मौजूद वस्तुएं किन वस्तुओं को भी संदर्भित करती हैं, और यदि वे सूची में भी हैं (हम देखेंगे कि वे एक पल में क्यों नहीं हो सकते हैं), आगे उनकी रिफरेक्ट को घटाता है। इस बिंदु पर (वास्तव में, कुछ ऐसे आंकड़े हैं जो यह निर्धारित करते हैं कि चीजें कब स्थानांतरित हो जाती हैं, लेकिन मान लें कि यह एक संग्रह के बाद चीजों को सरल रखने के लिए है) कुछ भी जो अभी भी एक से अधिक है 0 से अधिक एक और लिंक की गई सूची में पदोन्नत हो जाता है जिसे "जेनरेशन 1" कहा जाता है। (यही कारण है कि सभी ऑब्जेक्ट्स हमेशा 0 पीढ़ी में नहीं होते हैं) जिसके पास यह लूप कम बार लागू होता है। यह वह जगह है जहाँ जेनेरिक कचरा संग्रह आता है। पायथन में डिफ़ॉल्ट रूप से 3 पीढ़ियाँ हैं (वस्तुओं की तीन लिंक की गई सूची): पहली सूची (पीढ़ी 0) में सभी नई वस्तुएँ शामिल हैं; यदि GC चक्र होता है और ऑब्जेक्ट एकत्र नहीं होते हैं, तो वे दूसरी सूची (पीढ़ी 1) में स्थानांतरित हो जाते हैं, और यदि GC सूची दूसरी सूची में होती है और वे अभी भी एकत्र नहीं होते हैं, तो वे तीसरी सूची (पीढ़ी 2) में चले जाते हैं )। तीसरी पीढ़ी की सूची (जिसे "जेनरेशन 2" कहा जाता है, क्योंकि हम शून्य इंडेक्सिंग हैं) पहले दो की तुलना में बहुत कम बार कचरा इकट्ठा किया जाता है, यह विचार किया जा रहा है कि यदि आपकी वस्तु लंबे समय तक जीवित रहती है, तो इसकी संभावना नहीं है, और शायद कभी नहीं अपने आवेदन के जीवनकाल के दौरान GCed रहें, इसलिए हर एक GC रन पर इसे चेक करने में समय बर्बाद करने का कोई मतलब नहीं है। इसके अलावा, यह देखा गया है कि अधिकांश वस्तुएं अपेक्षाकृत जल्दी एकत्रित होती हैं। अब से, हम इन "अच्छी वस्तुओं" को कॉल करेंगे क्योंकि वे युवा मर जाते हैं। इसे "कमजोर उत्पत्ति संबंधी परिकल्पना" कहा जाता है और 60 के दशक में पहली बार देखा गया था।
एक तरफ एक त्वरित: पहली दो पीढ़ियों के विपरीत, लंबे समय तक रहने वाली तीसरी पीढ़ी की सूची नियमित समय पर एकत्र नहीं की जाती है। यह जाँच की जाती है कि लंबे समय से लंबित वस्तुओं का अनुपात (जो तीसरी पीढ़ी की सूची में हैं, लेकिन वास्तव में जीसी चक्र अभी तक नहीं है) सूची में कुल लंबे समय तक जीवित वस्तुओं का अनुपात 25% से अधिक है। ऐसा इसलिए है क्योंकि तीसरी सूची अनबाउंड है (चीजें इसे किसी अन्य सूची में स्थानांतरित नहीं की जाती हैं, इसलिए वे केवल तब चले जाते हैं जब वे वास्तव में कचरा एकत्र करते हैं), जिसका अर्थ है कि उन अनुप्रयोगों के लिए जहां आप बहुत सारी जीवित वस्तुओं का निर्माण कर रहे हैं, जीसी चक्र तीसरी सूची में काफी लंबा समय मिल सकता है। एक अनुपात का उपयोग करके हम "वस्तुओं की कुल संख्या में परिशोधित रैखिक प्रदर्शन" प्राप्त करते हैं; उर्फ, लंबी सूची, लंबी जीसी लगती है, लेकिन कम बार हम जीसी करते हैं (यहां फ्यूचर पढ़ने के लिए मार्टिन वॉन लोविस द्वारा इस अनुमान के लिए मूल 2008 का प्रस्ताव है )। तीसरी पीढ़ी या "परिपक्व" सूची पर कचरा संग्रह करने के कार्य को "पूर्ण कचरा संग्रह" कहा जाता है।
तो जेनेरिक कचरा संग्रह चीजों की गति को बहुत कम कर देता है, जिसकी आवश्यकता नहीं है कि हम उन वस्तुओं पर स्कैन करते हैं जो हर समय जीसी की आवश्यकता नहीं होती हैं, लेकिन यह हमें चक्रीय संदर्भों को तोड़ने में कैसे मदद करता है? शायद बहुत अच्छी तरह से नहीं, यह पता चला है। वास्तव में इन संदर्भ चक्रों को तोड़ने का कार्य इस तरह शुरू होता है:
/* Break reference cycles by clearing the containers involved. This is
* tricky business as the lists can be changing and we don't know which
* objects may be freed. It is possible I screwed something up here.
*/
static void
delete_garbage(PyGC_Head *collectable, PyGC_Head *old)
जनरेशनल कचरा संग्रह का कारण इसके साथ मदद करता है कि हम सूची की लंबाई को एक अलग गिनती के रूप में रख सकते हैं; जितनी बार हम इस गणना को बढ़ाते हैं उस पीढ़ी में एक नई वस्तु जोड़ते हैं, और किसी भी समय हम किसी वस्तु को दूसरी पीढ़ी में ले जाते हैं या उसे निपटाते हैं जो हम गिनती में वृद्धि करते हैं। जीसी चक्र के अंत में सैद्धांतिक रूप से यह गिनती (पहली दो पीढ़ियों के लिए वैसे भी) हमेशा 0. होनी चाहिए। यदि यह नहीं है, तो सूची में कुछ भी जो बचा है वह परिपत्र संदर्भ का कुछ रूप है और हम इसे छोड़ सकते हैं। हालांकि, यहां एक और समस्या है: क्या होगा अगर बचे हुए ऑब्जेक्ट्स में पायथन की जादू पद्धति __del__
उन पर है? __del__
कहा जाता है किसी भी समय एक पायथन वस्तु नष्ट हो जाती है। हालांकि, अगर एक गोलाकार संदर्भ में दो वस्तुओं में __del__
विधियां हैं, तो हम यह सुनिश्चित नहीं कर सकते कि एक को नष्ट करने से दूसरों की __del__
विधि भंग नहीं होगी। एक आकस्मिक उदाहरण के लिए, कल्पना करें कि हमने निम्नलिखित लिखा है:
class A(object):
def __init__(self, b=None):
self.b = b
def __del__(self):
print("We're deleting an instance of A containing:", self.b)
class B(object):
def __init__(self, a=None):
self.a = a
def __del__(self):
print("We're deleting an instance of B containing:", self.a)
और हम एक दूसरे को इंगित करने के लिए ए और बी का एक उदाहरण सेट करते हैं और फिर वे एक ही कचरा संग्रह चक्र में समाप्त हो जाते हैं? मान लें कि हम यादृच्छिक को उठाते हैं और पहले ए के हमारे उदाहरण को निपटाते हैं; A की __del__
विधि __del__
, यह प्रिंट होगी, फिर A को मुक्त किया जाएगा। आगे हम B पर आते हैं, हम इसकी __del__
विधि कहते हैं, और उफ़! Segfault! अब मौजूद नहीं है। हम पहले से ही __del__
तरीकों को छोड़ दी गई हर चीज को कॉल करके इसे ठीक कर सकते हैं, फिर वास्तव में सब कुछ करने के लिए एक और पास करते हैं, हालांकि, यह एक और परिचय देता है, मुद्दा: क्या होगा अगर एक वस्तु __del__
विधि दूसरे ऑब्जेक्ट के संदर्भ को सहेजती है जो GCed और के बारे में है कहीं और हमारे लिए एक संदर्भ है? हमारे पास अभी भी एक संदर्भ चक्र है, लेकिन अब यह वास्तव में जीसी या तो वस्तु के लिए संभव नहीं है, भले ही वे अब उपयोग में न हों। ध्यान दें कि भले ही कोई वस्तु एक गोलाकार डेटा संरचना का हिस्सा नहीं है, यह स्वयं अपने __del__
विधि में पुनर्जीवित कर सकता है; पाइथन के पास इसके लिए एक जांच है और अगर इसकी __del__
विधि को बुलाया जाता है, तो एक वस्तु की वापसी में वृद्धि होने पर GCing को रोक देगा।
CPython इसके साथ अन-जीसी-सक्षम ऑब्जेक्ट्स (कुछ प्रकार के परिपत्र संदर्भ और एक __del__
विधि के साथ कुछ भी) को __del__
कचरे की वैश्विक सूची में __del__
और फिर इसे सभी अनंत काल के लिए छोड़ देता है:
/* list of uncollectable objects */
static PyObject *garbage = NULL;
संदर्भ की गिनती
पाइथन मेमोरी मैनेजमेंट का अधिकांश हिस्सा संदर्भ गणना के साथ संभाला जाता है।
जब भी किसी वस्तु को संदर्भित किया जाता है (उदाहरण के लिए एक चर को सौंपा जाता है), तो उसकी संदर्भ संख्या अपने आप बढ़ जाती है। जब इसे घटाया जाता है (जैसे चर दायरे से बाहर हो जाता है), तो इसकी संदर्भ संख्या अपने आप कम हो जाती है।
जब संदर्भ गणना शून्य तक पहुंच जाती है, तो वस्तु तुरंत नष्ट हो जाती है और स्मृति तुरंत मुक्त हो जाती है। इस प्रकार अधिकांश मामलों के लिए, कचरा कलेक्टर की आवश्यकता भी नहीं है।
>>> import gc; gc.disable() # disable garbage collector
>>> class Track:
def __init__(self):
print("Initialized")
def __del__(self):
print("Destructed")
>>> def foo():
Track()
# destructed immediately since no longer has any references
print("---")
t = Track()
# variable is referenced, so it's not destructed yet
print("---")
# variable is destructed when function exits
>>> foo()
Initialized
Destructed
---
Initialized
---
Destructed
संदर्भों की अवधारणा को आगे प्रदर्शित करने के लिए:
>>> def bar():
return Track()
>>> t = bar()
Initialized
>>> another_t = t # assign another reference
>>> print("...")
...
>>> t = None # not destructed yet - another_t still refers to it
>>> another_t = None # final reference gone, object is destructed
Destructed
संदर्भ चक्र के लिए कचरा कलेक्टर
यदि आपके पास एक संदर्भ चक्र है, तो केवल कचरा कलेक्टर की आवश्यकता है। संदर्भ चक्र का उदाहरण उदाहरण वह है जिसमें A, B को संदर्भित करता है और B A को संदर्भित करता है, जबकि अन्य कुछ भी A या B को संदर्भित नहीं करता है। न तो A या B कार्यक्रम में कहीं से भी पहुँच योग्य हैं, इसलिए वे सुरक्षित रूप से नष्ट हो सकते हैं, अभी तक उनके संदर्भ संख्या 1 हैं और इसलिए उन्हें केवल संदर्भ गणना एल्गोरिथ्म द्वारा मुक्त नहीं किया जा सकता है।
>>> import gc; gc.disable() # disable garbage collector
>>> class Track:
def __init__(self):
print("Initialized")
def __del__(self):
print("Destructed")
>>> A = Track()
Initialized
>>> B = Track()
Initialized
>>> A.other = B
>>> B.other = A
>>> del A; del B # objects are not destructed due to reference cycle
>>> gc.collect() # trigger collection
Destructed
Destructed
4
एक संदर्भ चक्र मनमाना लंबा हो सकता है। यदि A, B को इंगित करता है, तो C को ... को इंगित करता है, जो A को इंगित करता है, तो न तो A को Z के माध्यम से एकत्र किया जाएगा, जब तक कि कचरा संग्रहण चरण:
>>> objs = [Track() for _ in range(10)]
Initialized
Initialized
Initialized
Initialized
Initialized
Initialized
Initialized
Initialized
Initialized
Initialized
>>> for i in range(len(objs)-1):
... objs[i].other = objs[i + 1]
...
>>> objs[-1].other = objs[0] # complete the cycle
>>> del objs # no one can refer to objs now - still not destructed
>>> gc.collect()
Destructed
Destructed
Destructed
Destructed
Destructed
Destructed
Destructed
Destructed
Destructed
Destructed
20
डेल कमांड के प्रभाव
del v
का उपयोग कर दायरे से एक चर नाम को हटाना, या del v[item]
या del[i:j]
का उपयोग करके किसी संग्रह से एक वस्तु को हटाना, या del v.name
। या किसी अन्य तरीके से संदर्भ को हटाने का उपयोग करके किसी विशेषता को हटाना। एक वस्तु, किसी भी नाशक कॉल ट्रिगर नहीं करता या किसी स्मृति में और स्वयं का मुक्त कर दिया जा रहा है। वस्तुओं को केवल तब नष्ट किया जाता है जब उनकी संदर्भ संख्या शून्य तक पहुंच जाती है।
>>> import gc
>>> gc.disable() # disable garbage collector
>>> class Track:
def __init__(self):
print("Initialized")
def __del__(self):
print("Destructed")
>>> def bar():
return Track()
>>> t = bar()
Initialized
>>> another_t = t # assign another reference
>>> print("...")
...
>>> del t # not destructed yet - another_t still refers to it
>>> del another_t # final reference gone, object is destructed
Destructed
आदिम वस्तुओं का पुन: उपयोग
ध्यान देने वाली एक दिलचस्प बात जो आपके अनुप्रयोगों को अनुकूलित करने में मदद कर सकती है वह यह है कि आदिम वास्तव में हुड के नीचे भी हैं। आइए संख्याओं पर एक नज़र डालें; -5 और 256 के बीच सभी पूर्णांकों के लिए, पायथन हमेशा एक ही वस्तु का पुन: उपयोग करता है:
>>> import sys
>>> sys.getrefcount(1)
797
>>> a = 1
>>> b = 1
>>> sys.getrefcount(1)
799
ध्यान दें कि प्रतिफल बढ़ता है, जिसका अर्थ है कि a
और b
a
ही अंतर्निहित वस्तु का संदर्भ देते हैं जब वे 1
आदिम को संदर्भित करते हैं। हालाँकि, बड़ी संख्या के लिए, पायथन वास्तव में अंतर्निहित वस्तु का पुन: उपयोग नहीं करता है:
>>> a = 999999999
>>> sys.getrefcount(999999999)
3
>>> b = 999999999
>>> sys.getrefcount(999999999)
3
क्योंकि 999999999
लिए 999999999
बदलाव नहीं होता है क्योंकि इसे a
और b
को असाइन करने पर हम अनुमान लगा सकते हैं कि वे दो अलग-अलग अंतर्निहित वस्तुओं का उल्लेख करते हैं, भले ही वे दोनों एक ही आदिम असाइन किए गए हों।
किसी वस्तु का प्रतिफलन देखना
>>> import sys
>>> a = object()
>>> sys.getrefcount(a)
2
>>> b = a
>>> sys.getrefcount(a)
3
>>> del b
>>> sys.getrefcount(a)
2
जबरदस्ती वस्तुओं का निपटारा करना
आप ऑब्जेक्ट को हटा सकते हैं, भले ही उनका पाइथन 2 और 3 दोनों में रिफकाउंट न हो।
दोनों संस्करण ऐसा करने के लिए ctypes
मॉड्यूल का उपयोग करते हैं।
चेतावनी: ऐसा करने से आपका पायथन वातावरण अस्थिर होगा और ट्रेसबैक के बिना दुर्घटनाग्रस्त होने का खतरा होगा! इस पद्धति का उपयोग करने से सुरक्षा समस्याएँ भी सामने आ सकती हैं (काफी असंभावित) केवल उन वस्तुओं को हटा दें जिनके बारे में आप सुनिश्चित हैं कि आप फिर कभी संदर्भ नहीं देंगे। कभी।
import ctypes
deallocated = 12345
ctypes.pythonapi._Py_Dealloc(ctypes.py_object(deallocated))
import ctypes, sys
deallocated = 12345
(ctypes.c_char * sys.getsizeof(deallocated)).from_address(id(deallocated))[:4] = '\x00' * 4
दौड़ने के बाद, अब निपटाए गए ऑब्जेक्ट के किसी भी संदर्भ में पाइथन के कारण या तो बिना किसी अपरिचित व्यवहार या दुर्घटना के उत्पादन होगा - ट्रेसबैक के बिना। शायद एक कारण था कि कचरा संग्रहकर्ता ने उस वस्तु को क्यों नहीं हटाया ...
यदि आप None
, तो आपको एक विशेष संदेश मिलता है - Fatal Python error: deallocating None
दुर्घटनाग्रस्त होने से पहले Fatal Python error: deallocating None
।
कचरा संग्रहण का प्रबंध करना
एक मेमोरी क्लीनअप करने पर प्रभावित करने के दो तरीके हैं। वे यह प्रभावित कर रहे हैं कि स्वचालित प्रक्रिया कितनी बार की जाती है और दूसरी मैन्युअल रूप से सफाई शुरू कर रही है।
कलेक्शन थ्रेसहोल्ड को ट्यून करके कचरा कलेक्टर में हेरफेर किया जा सकता है जो उस आवृत्ति को प्रभावित करता है जिस पर कलेक्टर चलता है। पायथन एक पीढ़ी आधारित स्मृति प्रबंधन प्रणाली का उपयोग करता है। नई वस्तुओं को नई पीढ़ी में बचाया जाता है - Gener0 और प्रत्येक जीवित संग्रह के साथ, वस्तुओं को पुरानी पीढ़ियों तक बढ़ावा दिया जाता है। अंतिम पीढ़ी - पीढ़ी 2 तक पहुंचने के बाद, अब उनका प्रचार नहीं किया जाता है।
निम्नलिखित स्निपेट का उपयोग करके थ्रेसहोल्ड को बदला जा सकता है:
import gc
gc.set_threshold(1000, 100, 10) # Values are just for demonstration purpose
पहला तर्क जनरेशन इकट्ठा करने की सीमा का प्रतिनिधित्व करता है। हर बार जब आवंटन की संख्या 1000 से deallocations की संख्या से अधिक कचरा कलेक्टर बुलाया जाएगा।
प्रक्रिया को अनुकूलित करने के लिए पुरानी पीढ़ियों को प्रत्येक रन पर साफ नहीं किया जाता है। दूसरी और तीसरी दलीलें वैकल्पिक हैं और नियंत्रित करती हैं कि पुरानी पीढ़ियों को कितनी बार साफ किया जाता है। यदि generation0 generation1 सफाई के बिना 100 बार संसाधित किया गया था, तो generation1 कार्रवाई की जाएगी। इसी प्रकार, जनरेशन 2 में वस्तुओं को केवल तभी संसाधित किया जाएगा जब जनरेशन 1 में बिना जनरेशन टच 2 के 10 बार सफाई की गई हो।
एक उदाहरण जिसमें थ्रेशोल्ड को मैन्युअल रूप से सेट करना फायदेमंद है, जब प्रोग्राम बहुत सी छोटी वस्तुओं को बिना डील किए आवंटित करता है, जो कचरा संग्रहकर्ता को अक्सर चलता है (प्रत्येक पीढ़ी0_थ्रेशोल्ड ऑब्जेक्ट आवंटन)। हालांकि, कलेक्टर बहुत तेज है, जब यह भारी संख्या में वस्तुओं पर चलता है तो यह एक प्रदर्शन मुद्दा बनता है। वैसे भी, कोई भी आकार थ्रेसहोल्ड चुनने के लिए सभी रणनीति को फिट नहीं करता है और यह भरोसेमंद मामले का उपयोग करता है।
निम्न स्निपेट में संग्रह को मैन्युअल रूप से ट्रिगर किया जा सकता है:
import gc
gc.collect()
कचरे का संग्रह स्वचालित रूप से आबंटित और डीलॉक्लेशन की संख्या के आधार पर ट्रिगर किया जाता है, न कि भस्म या उपलब्ध स्मृति पर। नतीजतन, बड़ी वस्तुओं के साथ काम करते समय, स्वचालित क्लीनअप ट्रिगर होने से पहले मेमोरी कम हो सकती है। यह कचरा कलेक्टर को मैन्युअल रूप से कॉल करने के लिए एक अच्छा उपयोग मामला बनाता है।
हालांकि यह संभव है, यह एक प्रोत्साहित अभ्यास नहीं है। मेमोरी लीक से बचना सबसे अच्छा विकल्प है। वैसे भी, स्मृति रिसाव का पता लगाने वाली बड़ी परियोजनाओं में हालांकि एक कार्य हो सकता है और मैन्युअल रूप से कचरा संग्रह को ट्रिगर करना त्वरित डिबगिंग तक एक त्वरित समाधान के रूप में उपयोग किया जा सकता है।
लंबे समय तक चलने वाले कार्यक्रमों के लिए, कचरा संग्रह को समय के आधार पर या घटना के आधार पर चालू किया जा सकता है। पहले एक के लिए एक उदाहरण एक वेब सर्वर है जो निश्चित संख्या के अनुरोधों के बाद एक संग्रह को ट्रिगर करता है। बाद में, एक वेब सर्वर जो एक निश्चित प्रकार का अनुरोध प्राप्त होने पर कचरा संग्रह को ट्रिगर करता है।
कचरा संग्रह के साफ होने का इंतजार न करें
तथ्य यह है कि कचरा संग्रह साफ हो जाएगा इसका मतलब यह नहीं है कि आपको कचरा संग्रह चक्र की सफाई के लिए इंतजार करना चाहिए।
विशेष रूप से आपको फ़ाइल संग्रह, डेटाबेस कनेक्शन और खुले नेटवर्क कनेक्शन को बंद करने के लिए कचरा संग्रह की प्रतीक्षा नहीं करनी चाहिए।
उदाहरण के लिए:
निम्नलिखित कोड में, आप मान लेते हैं कि फ़ाइल अगले कचरा संग्रह चक्र पर बंद हो जाएगी, अगर फ़ाइल का अंतिम संदर्भ f था।
>>> f = open("test.txt")
>>> del f
सफाई करने का एक अधिक स्पष्ट तरीका f.close()
को कॉल f.close()
। आप इसे और भी सुरुचिपूर्ण तरीके से कर सकते हैं, जो कि कथन के with
उपयोग किया जाता है, जिसे संदर्भ प्रबंधक के रूप में भी जाना जाता है:
>>> with open("test.txt") as f:
... pass
... # do something with f
>>> #now the f object still exists, but it is closed
स्टेटमेंट के with
आप खुली फाइल के तहत अपने कोड को इंडेंट कर सकते हैं। इससे यह स्पष्ट और आसान हो जाता है कि किसी फ़ाइल को कितनी देर तक खुला रखा जाए। यह भी हमेशा एक फ़ाइल बंद कर देता है, भले ही एक अपवाद में उठाया है while
ब्लॉक।