क्या पूरी फ़ाइल पढ़ने से फ़ाइल हैंडल खुली रहती है?


372

यदि आप एक पूरी फ़ाइल पढ़ते हैं, content = open('Path/to/file', 'r').read()तो स्क्रिप्ट के बाहर निकलने तक फ़ाइल हैंडल खुला रहता है? क्या पूरी फ़ाइल पढ़ने के लिए अधिक संक्षिप्त विधि है?

जवाबों:


585

उस प्रश्न का उत्तर कुछ विशेष रूप से पायथन कार्यान्वयन पर निर्भर करता है।

यह समझने के लिए कि यह सब क्या है, वास्तविक fileवस्तु पर विशेष ध्यान दें । आपके कोड में, उस ऑब्जेक्ट का उल्लेख केवल एक बार किया जाता है, एक अभिव्यक्ति में, और read()कॉल रिटर्न के तुरंत बाद दुर्गम हो जाता है।

इसका मतलब है कि फ़ाइल ऑब्जेक्ट कचरा है। केवल शेष प्रश्न "कचरा कलेक्टर फ़ाइल ऑब्जेक्ट को कब एकत्र करेगा?"।

सीपीथॉन में, जो एक संदर्भ काउंटर का उपयोग करता है, इस तरह का कचरा तुरंत देखा जाता है, और इसलिए इसे तुरंत एकत्र किया जाएगा। यह आमतौर पर अन्य अजगर कार्यान्वयनों के बारे में सच नहीं है।

एक बेहतर समाधान, यह सुनिश्चित करने के लिए कि फ़ाइल बंद है, क्या यह पैटर्न है:

with open('Path/to/file', 'r') as content_file:
    content = content_file.read()

जो हमेशा ब्लॉक समाप्त होने के तुरंत बाद फ़ाइल को बंद कर देगा; भले ही कोई अपवाद हो।

संपादित करें: इस पर एक महीन बिंदु डालने के लिए:

अन्य के अलावा file.__exit__(), जो "स्वचालित रूप से" एक withसंदर्भ प्रबंधक सेटिंग में कहा जाता है , एकमात्र तरीका है file.close()जिसे स्वचालित रूप से कहा जाता है (अर्थात, स्पष्ट रूप से खुद को कॉल करने के अलावा,) file.__del__()। यह हमें इस सवाल की ओर ले जाता है कि हमें कब __del__()बुलाया जाता है?

एक सही ढंग से लिखा कार्यक्रम यह नहीं मान सकता है कि कार्यक्रम समाप्ति से पहले कभी भी अंतिम बिंदु किसी भी बिंदु पर चलेगा।

- https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203

विशेष रूप से:

वस्तुओं को कभी भी स्पष्ट रूप से नष्ट नहीं किया जाता है; हालांकि, जब वे पहुंच से बाहर हो जाते हैं, तो वे कचरा एकत्र किए जा सकते हैं। कचरा संग्रहण को स्थगित करने या इसे पूरी तरह से छोड़ने के लिए एक कार्यान्वयन की अनुमति दी जाती है - यह कार्यान्वयन गुणवत्ता का मामला है कि कचरा संग्रह कैसे लागू किया जाता है, जब तक कि कोई भी वस्तु एकत्र नहीं की जाती है जो अभी भी उपलब्ध हैं।

[...]

CPython वर्तमान में एक संदर्भ-गणना योजना का उपयोग करता है, जिसके साथ (वैकल्पिक) विलंबित रूप से लिंक किए गए कचरे का पता लगाने में देरी होती है, जो ज्यादातर वस्तुओं को इकट्ठा करते हैं जैसे ही वे पहुंच से बाहर हो जाते हैं, लेकिन परिपत्र संदर्भ वाले कचरे को इकट्ठा करने की गारंटी नहीं है।

- https://docs.python.org/3.5/reference/datamodel.html#objects-values-and-ypes

(जोर मेरा)

लेकिन जैसा कि यह सुझाव है, अन्य कार्यान्वयन अन्य व्यवहार हो सकता है। एक उदाहरण के रूप में, PyPy में 6 अलग-अलग कचरा संग्रह कार्यान्वयन हैं !


24
कुछ समय के लिए, वास्तव में अन्य पायथन कार्यान्वयन नहीं थे; लेकिन कार्यान्वयन विवरण पर भरोसा करना वास्तव में पाइथोनिक नहीं है।
कार्ल केनचेल

क्या यह अभी भी कार्यान्वयन-विशिष्ट है, या यह पहले से ही मानकीकृत था? __exit__()ऐसे मामलों में कॉल न करना एक डिज़ाइन दोष की तरह लगता है।
rr-

2
@jgmjgm उन 3 मुद्दों की वजह से यह ठीक है, जीसी अप्रत्याशित हो, try/ finallyजमकर हो रहा है और सफाई करने वाले हैंडलर्स की अत्यधिक सामान्य उपयोगी है जो withहल करता है। "स्पष्ट रूप से समापन" और "के साथ प्रबंधन" के बीच का अंतर यह withहै कि अपवाद हैंडलर को अपवाद कहे जाने पर भी कहा जाता है। आप इसे close()एक finallyक्लॉज़ में डाल सकते हैं , लेकिन withइसके बजाय इसका उपयोग करने से बहुत अलग नहीं है , थोड़ा गड़बड़ (1 के बजाय 3 अतिरिक्त लाइनें), और बस सही पाने के लिए थोड़ा कठिन है।
सिंगलएनजेशन इलेक्शन

1
मुझे इस बारे में जानकारी नहीं है कि क्यों 'साथ' अब विश्वसनीय होगा क्योंकि यह या तो स्पष्ट नहीं है। क्या यह इसलिए है क्योंकि कल्पना कहती है कि उसे ऐसा करना है जो हमेशा उसी तरह लागू हो?
jgmjgm

3
@jgmjgm इसे और अधिक विश्वसनीय है क्योंकि है with foo() as f: [...]मूल रूप से रूप में ही है f = foo(), f.__enter__(), [...] और f.__exit__() संभाला अपवादों के साथ , ताकि __exit__हमेशा कहा जाता है। तो फ़ाइल हमेशा बंद हो जाती है।
नवगीतकार

104

आप पाथलिब का उपयोग कर सकते हैं ।

पायथन 3.5 और उससे अधिक के लिए:

from pathlib import Path
contents = Path(file_path).read_text()

पायथन के पुराने संस्करणों के लिए pathlib2 का उपयोग करें :

$ pip install pathlib2

फिर:

from pathlib2 import Path
contents = Path(file_path).read_text()

यह वास्तविक read_text कार्यान्वयन है :

def read_text(self, encoding=None, errors=None):
    """
    Open the file in text mode, read it, and close the file.
    """
    with self.open(mode='r', encoding=encoding, errors=errors) as f:
        return f.read()

2

ठीक है, अगर आपको प्रत्येक पंक्ति के साथ काम करने के लिए लाइन से फाइल लाइन पढ़ना है, तो आप उपयोग कर सकते हैं

with open('Path/to/file', 'r') as f:
    s = f.readline()
    while s:
        # do whatever you want to
        s = f.readline()

या इससे भी बेहतर तरीका:

with open('Path/to/file') as f:
    for line in f:
        # do whatever you want to

0

फ़ाइल सामग्री को एक स्ट्रिंग के रूप में पुनर्प्राप्त करने के बजाय, सामग्री को संग्रहीत करना आसान हो सकता है क्योंकि फ़ाइल में सभी पंक्तियों की सूची शामिल है :

with open('Path/to/file', 'r') as content_file:
    content_list = content_file.read().strip().split("\n")

जैसा कि देखा जा सकता है, इस धागे में मुख्य उत्तर में संक्षिप्त तरीकों .strip().split("\n")को जोड़ने की आवश्यकता है ।

यहाँ, .strip()पूरे फाइल स्ट्रिंग के अंत में सिर्फ व्हाट्सएप और न्यूलाइन वर्णों को हटाता है, और .split("\n")प्रत्येक न्यूलाइन वर्ण \ n पर संपूर्ण फ़ाइल स्ट्रिंग को विभाजित करके वास्तविक सूची तैयार करता है ।

इसके अलावा, इस तरह से पूरी फ़ाइल सामग्री को एक चर में संग्रहित किया जा सकता है, जो कुछ मामलों में वांछित हो सकती है, बजाय इस पिछले उत्तर में बताए फ़ाइल लाइन पर लूपिंग के बजाय ।

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