क्या फ़ाइलों को स्पष्ट रूप से बंद करना महत्वपूर्ण है?


149

पायथन में, यदि आप या तो कॉल किए बिना फ़ाइल खोलते हैं close(), या फ़ाइल को बंद करते हैं, लेकिन उपयोग नहीं कर रहे हैं try- finallyया " with" स्टेटमेंट, क्या यह एक समस्या है? या यह सभी फ़ाइलों को बंद करने के लिए पायथन कचरा-संग्रह पर भरोसा करने के लिए एक कोडिंग अभ्यास के रूप में पर्याप्त है? उदाहरण के लिए, यदि कोई ऐसा करता है:

for line in open("filename"):
    # ... do stuff ...

... क्या यह एक समस्या है क्योंकि फ़ाइल कभी भी बंद नहीं हो सकती है और एक अपवाद हो सकता है जो इसे बंद होने से रोकता है? या यह निश्चित रूप से forबयान के समापन पर बंद हो जाएगा क्योंकि फ़ाइल गुंजाइश से बाहर जाती है?


13
फ़ाइल ब्लॉक के अंत में दायरे से बाहर नहीं जाती है for। इसकी संदर्भ गणना शून्य पर जाएगी, जिससे यह स्वचालित रूप से बंद हो जाएगी, लेकिन केवल फ़ंक्शन, कक्षाएं और मॉड्यूल पायथन में स्कोप को परिभाषित करते हैं, अन्य यौगिक विवरण नहीं।
agf

18
यह एक समस्या नहीं है जब तक कि यह एक समस्या नहीं है। ओएस स्तर पर, स्क्रिप्ट द्वारा खोली गई कोई भी फाइल स्क्रिप्ट से बाहर निकलते समय बंद हो जाएगी, इसलिए आपको थ्रोअवे स्क्रिप्ट में फ़ाइलों को बंद करने के बारे में चिंता करने की आवश्यकता नहीं है। हालांकि, प्रक्रियाओं में उन खुली फ़ाइलों की संख्या की सीमा होती है जिन्हें वे बनाए रख सकते हैं, इसलिए लंबे समय तक जीवित या जटिल लिपियों के लिए अधिक सावधान रहने की आवश्यकता हो सकती है। किसी भी मामले में, अपनी फ़ाइलों को बंद करना एक अच्छी आदत है।
रसेल बोरोगोव

3
@agf: आप सही कह रहे हैं कि फ़ाइल दायरे से बाहर नहीं जाती है, लेकिन यह forब्लॉक और फ़ंक्शंस / क्लासेस / मॉड्यूल के बीच के अंतर से संबंधित नहीं है । यह उससे बहुत सरल है: वस्तुओं में स्कोप नहीं हैं, केवल नाम हैं। इस ऑब्जेक्ट को संदर्भित करने वाला कोई नाम नहीं है, इसलिए स्कोप में रहने या स्कोप से बाहर जाने के लिए यहां कुछ भी नहीं है।
अधिकतम

@ मेरी टिप्पणी उनकी धारणा को सही कर रही है कि forलूप से जुड़ा एक दायरा है , और यह उल्लेख करते हुए कि फ़ाइल पूरी तरह से अलग कारण से बंद हो जाती है। यह पायथन में क्या स्कोप नहीं है, क्योंकि यह यहां प्रासंगिक नहीं है।
agf

@ मोम का एक निहित संदर्भ है जो लूप के लिए स्कूप किया गया है ... यह शब्दार्थ का एक तर्क है
पीटर आर

जवाबों:


126

आपके उदाहरण में दुभाषिया के बाहर निकलने से पहले फ़ाइल को बंद करने की गारंटी नहीं है। CPython के वर्तमान संस्करणों में फ़ाइल को लूप के अंत में बंद कर दिया जाएगा क्योंकि CPython संदर्भ गिनती को अपने प्राथमिक कचरा संग्रह तंत्र के रूप में उपयोग करता है लेकिन यह एक कार्यान्वयन विवरण है, भाषा की विशेषता नहीं है। अजगर के अन्य कार्यान्वयन इस तरह से काम करने की गारंटी नहीं है। उदाहरण के लिए IronPython, PyPy, और Jython संदर्भ गिनती का उपयोग नहीं करते हैं और इसलिए लूप के अंत में फ़ाइल को बंद नहीं करेंगे।

CPython के कचरा संग्रहण कार्यान्वयन पर भरोसा करना बुरा है क्योंकि यह आपके कोड को कम पोर्टेबल बनाता है। यदि आप CPython का उपयोग करते हैं, तो आपके पास संसाधन लीक नहीं हो सकते हैं, लेकिन यदि आप कभी भी Python कार्यान्वयन पर स्विच करते हैं जो संदर्भ गिनती का उपयोग नहीं करता है, तो आपको अपने सभी कोड के माध्यम से जाने और यह सुनिश्चित करने की आवश्यकता होगी कि आपकी सभी फ़ाइलें ठीक से बंद हैं।

अपने उदाहरण के लिए उपयोग करें:

with open("filename") as f:
     for line in f:
        # ... do stuff ...

8
क्या with open() as fफ़ाइल का उपयोग करने के बाद यह स्वतः ही बंद हो जाता है?
रोहन

24
@ रोहन हाँ, यह एक छोटा सा जादू है जो withकथन प्रदान करता है, लेकिन निश्चित रूप से इस जादू के लिए ऑब्जेक्ट को काम करने के लिए विशिष्ट तरीके होने चाहिए__enter__ और __exit__, बाद में वस्तु closeऔर किसी भी अन्य सफाई सामान की आवश्यकता होती है। withबयान का अंत ...
कॉपरफील्ड

1
FYI करें: यह उत्तर केवल यह बताता है कि "यह कब बंद होगा" लेकिन यह नहीं समझाता है कि "यदि यह खुला रहता है तो क्या होगा"। उत्तरार्द्ध के लिए, कृपया "फ़ाइल खुले रहने पर क्या होगा?" इस उत्तर में हिस्सा ( askubuntu.com/questions/701491/… )
रेअलू

इसके अलावा, फाइलों को बंद न करने से फ़ाइलों में छंटनी हो सकती है क्योंकि फाइल सामग्री को फ्लश नहीं किया गया है।
एरवान लेग्रैंड

इसलिए यदि मैं फ़ाइल बंद नहीं करता हूं, तो क्या प्रोग्राम बंद होने के बाद मुझे अपनी मेमोरी वापस मिल जाएगी? या क्या मुझे वास्तव में पूरे दुभाषिया से बाहर निकलना होगा?
प्रो क्यू

22

कुछ अजगर स्वचालित रूप से फ़ाइलों को बंद कर देंगे जब वे अब संदर्भित नहीं होते हैं, जबकि अन्य नहीं करेंगे और यह पायथन दुभाषिया से बाहर निकलने पर फ़ाइलों को बंद करने के लिए ओ / एस पर निर्भर है।

यहां तक ​​कि पायथन के लिए जो आपके लिए फाइलें बंद कर देगा, समय की गारंटी नहीं है: यह तुरंत हो सकता है, या यह सेकंड / मिनट / घंटे / दिन बाद हो सकता है।

इसलिए, जब आप अपने द्वारा उपयोग किए जा रहे अजगर के साथ समस्याओं का अनुभव नहीं कर सकते हैं, तो निश्चित रूप से अपनी फ़ाइलों को खुला छोड़ना अच्छा अभ्यास नहीं है। वास्तव में, cpython 3 में आपको अब चेतावनी मिलेगी कि यदि आपने ऐसा नहीं किया तो सिस्टम को आपके लिए फाइलें बंद करनी होंगी।

Moral: अपने आप के बाद साफ। :)


9
सीपीयथॉन में संदर्भित नहीं होने पर फाइलें बंद हो जाती हैं, लेकिन यह एक भाषा सुविधा नहीं है। अगर यह तुम पर काफी खुशी से भरोसा कर सकता था।
पीटर ग्राहम

9

हालांकि इस विशेष मामले में इस तरह के निर्माण का उपयोग करना काफी सुरक्षित है, इस तरह के अभ्यास को सामान्य बनाने के लिए कुछ चेतावनी हैं:

  • रन संभावित रूप से फ़ाइल डिस्क्रिप्टर से बाहर निकल सकता है, हालांकि संभावना नहीं है, उस तरह एक बग का शिकार करने की कल्पना करें
  • आप कुछ सिस्टम, उदाहरण के लिए win32 पर उक्त फ़ाइल को हटाने में सक्षम नहीं हो सकते हैं
  • यदि आप CPython के अलावा कुछ भी चलाते हैं, तो आप नहीं जानते कि आपके लिए फ़ाइल कब बंद है
  • यदि आप फ़ाइल को लिखने या पढ़ने-लिखने के मोड में खोलते हैं, तो आपको पता नहीं है कि डेटा कब फ्लश हो जाता है

3

फ़ाइल कचरा एकत्र कर लेती है, और इसलिए बंद हो जाती है। जीसी निर्धारित करता है जब यह बंद हो जाता है, तो आप नहीं। जाहिर है, यह एक अनुशंसित अभ्यास नहीं है क्योंकि आप खुली फ़ाइल हैंडल सीमा से टकरा सकते हैं यदि आप फ़ाइलों का उपयोग करते समय समाप्त नहीं करते हैं। क्या होगा अगर आपके उस forपाश के भीतर , आप अधिक फाइलें खोलते हैं और उन्हें छोड़ देते हैं?


लेकिन अगर आपने लूप के लिए अन्य फाइलें खोली हैं, तब भी यह मामला होगा कि एक साथ एक से अधिक फाइल खुली होंगी या नहीं, आप स्पष्ट रूप से उनमें से किसी को बंद कर सकते हैं या नहीं। क्या आप कह रहे हैं कि फ़ाइल आवश्यक रूप से कचरा-संग्रहित नहीं है, जैसे ही फ़ाइल दायरे से बाहर हो जाती है, इस प्रकार यदि यह स्पष्ट रूप से बंद हो जाता है? क्या होता है जब एक अपवाद होता है (जब आप उपयोग करते हैं / कोशिश-अंत में बनाम ऐसा नहीं करते हैं)?
user553702

1
CPython में, संदर्भ गिनती के कारण forकथन के बाद इसे एकत्र किया जाएगा - आपको अगले कचरा संग्रह के चलने की प्रतीक्षा नहीं करनी होगी।
एएफएफ

3

नमस्ते अपनी स्थिति में अपनी फ़ाइल डिस्क्रिप्टर को बंद करना बहुत महत्वपूर्ण है जब आप उसी अजगर स्क्रिप्ट में इसका उपयोग करने जा रहे हैं। मैं आज खुद को इतनी लंबी डिबगिंग के बाद महसूस करता हूं। इसका कारण यह है कि आपके द्वारा विवरण फाइल करने के बाद ही सामग्री को संपादित / हटाया / सहेजा जाएगा और फ़ाइल में परिवर्तन प्रभावित होते हैं!

तो मान लीजिए कि आपके पास ऐसी स्थिति है कि आप एक नई फ़ाइल में सामग्री लिखते हैं और फिर fd को बंद किए बिना आप उस फ़ाइल का उपयोग कर रहे हैं (fd नहीं) एक अन्य शेल कमांड में जो उसकी सामग्री को पढ़ता है। इस स्थिति में आपको शेल कमांड के लिए आपको अपेक्षित रूप से सामग्री नहीं मिलेगी और यदि आप डीबग करने का प्रयास करते हैं तो आप बग को आसानी से नहीं ढूंढ सकते हैं। आप मेरे ब्लॉग प्रविष्टि http://magngantzps.blogspot.in/2014/04/importance-of-closing-file-descriptor.html पर और अधिक पढ़ सकते हैं


1

I / O प्रक्रिया के दौरान, डेटा बफ़र किया जाता है: इसका मतलब है कि यह फ़ाइल में लिखे जाने से पहले एक अस्थायी स्थान पर रखा गया है।

पायथन बफर को फ्लश नहीं करता है - अर्थात, फ़ाइल में डेटा लिखें- जब तक यह सुनिश्चित न हो कि आप लेखन कर रहे हैं। ऐसा करने का एक तरीका फ़ाइल को बंद करना है।

यदि आप किसी फ़ाइल को बंद किए बिना लिखते हैं, तो डेटा उसे लक्ष्य फ़ाइल में नहीं बनाएगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.