2013-01-29 14 views
20

यह निर्धारित करते समय कि कोई फ़ाइल मौजूद है या नहीं, कोशिश कथन का उपयोग कैसे करें "रेस हालत" से बचें?कोशिश कथन का उपयोग कैसे दौड़ की स्थिति से बचता है?

मैं पूछ रहा हूं क्योंकि एक अत्यधिक अपरिवर्तित answer (अद्यतन: इसे हटा दिया गया था) ऐसा लगता है कि os.path.exists() का उपयोग ऐसा अवसर बनाता है जो अन्यथा मौजूद नहीं होगा।

दिए गए उदाहरण

है:

try: 
    with open(filename): pass 
except IOError: 
    print 'Oh dear.' 

लेकिन मैं समझ नहीं कर रहा हूँ कैसे कि की तुलना में एक रेस स्थिति से बचा जाता है:

if not os.path.exists(filename): 
    print 'Oh dear.' 

os.path.exists(filename) कैसे बुला करता है के साथ कुछ करने के लिए हमलावर की अनुमति देते हैं फ़ाइल है कि वे पहले से ही नहीं कर सका?

उत्तर

24

रेस स्थिति है , ज़ाहिर है, आपके प्रोग्राम और फ़ाइल पर चलने वाले किसी अन्य कोड के बीच (दौड़ की स्थिति को हमेशा कम से कम दो समांतर प्रक्रियाओं या धागे की आवश्यकता होती है, विवरण के लिए this देखें)। यही कारण है कि open() बजाय exists() का उपयोग कर वास्तव में केवल दो स्थितियों में मदद मिल सकती अर्थ है:

  1. आपको लगता है कि या कुछ पृष्ठभूमि प्रक्रिया (द्वारा बनाई गई है नष्ट कर दिया एक फ़ाइल के होने की जाँच हालांकि, आप एक वेब सर्वर, कि अक्सर अंदर चलाते हैं इसका मतलब है कि आपकी प्रक्रिया की कई प्रतियां HTTP अनुरोधों को संसाधित करने के समानांतर में चल रही हैं, इसलिए वेब ऐप्स के लिए दौड़ की स्थिति संभव है, भले ही कोई अन्य प्रोग्राम न हो)।
  2. कुछ दुर्भावनापूर्ण प्रोग्राम चल रहा है जो आपके द्वारा मौजूद होने वाले क्षणों पर फ़ाइल को नष्ट कर अपने कोड को क्रैश करने का प्रयास कर रहा है।

exists() बस एक ही चेक करता है। अगर फ़ाइल मौजूद है, तो exists()True लौटाए जाने के बाद इसे माइक्रोसॉन्ड हटा दिया जा सकता है। अगर फ़ाइल अनुपस्थित है, तो इसे तुरंत बनाया जा सकता है।

हालांकि, open() न केवल फ़ाइल अस्तित्व के लिए परीक्षण करता है, बल्कि फ़ाइल खोलता है (और इन दोनों कार्यों को परमाणु रूप से करता है, इसलिए चेक और उद्घाटन के बीच कुछ भी नहीं हो सकता है)। आमतौर पर फ़ाइलों को हटाया नहीं जा सकता है जबकि वे किसी के द्वारा खुले होते हैं। इसका मतलब है कि with के अंदर आप पूरी तरह से सुनिश्चित हो सकते हैं: फ़ाइल खुली होने के बाद से वास्तव में मौजूद है। हालांकि यह केवल with के अंदर सच है, और फ़ाइल को with ब्लॉक निकास के तुरंत बाद हटाया जा सकता है, with के अंदर मौजूद फ़ाइल को रखने की आवश्यकता वाले कोड को गारंटी देता है कि कोड विफल नहीं होगा।

9

यहाँ उपयोग के एक उदाहरण है:

try: 
    with open('filename') as f: 
     do_stuff_that_depends_on_the_existence_of_the_file(f) 
except IOError as e: 
    print 'Trouble opening file' 

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

try फ़ाइल खोलने के कार्य की त्रुटि या सफलता का पता लगाने का एक तरीका है, क्योंकि पाइथन में फ़ाइल I/O एपीआई में आमतौर पर रिटर्न कोड नहीं होते हैं (इसके बजाय अपवाद का उपयोग किया जाता है)। तो वास्तव में अपने प्रश्न का उत्तर देने के लिए, यह try नहीं है जो दौड़ की स्थिति से बचाता है, यह open है। यह मूल रूप से सी में समान है (जिस पर पाइथन आधारित है), लेकिन अपवादों के बिना। अधिक जानकारी के लिए this पढ़ें।

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

कॉलिंग os.path.exists कॉलिंग समय पर एक पल में स्नैपशॉट देता है जब फ़ाइल मौजूद हो सकती है या नहीं हो सकती है, और आपको os.path.exists रिटर्न के बाद फ़ाइल के अस्तित्व का कोई ज्ञान नहीं है। Malevolent कोड या अप्रत्याशित तर्क फ़ाइल को हटा या बदल सकता है जब आप इसकी अपेक्षा नहीं कर रहे हैं। यह आपके सिर को मोड़ने के समान है कि यह जांचने से पहले एक सड़क स्पष्ट हो। एक बार जब आप अपना सिर वापस कर लेंगे, तो आपके पास यह अनुमान लगाने के अलावा कुछ भी नहीं है कि आप कहां जा रहे हैं। फ़ाइल खोलने पर एक विस्तारित संगत स्थिति की गारंटी होती है, ड्राइविंग करते समय कुछ भी संभव नहीं है (अच्छे या बीमार के लिए)। :)

try/open का उपयोग करने के बजाए फ़ाइल मौजूद नहीं है, यह जांचने का आपका सुझाव अभी भी os.path.exists की स्नैपशॉट प्रकृति के कारण अपर्याप्त है। दुर्भाग्यवश मुझे सभी मामलों में निर्देशिका में फ़ाइलों को बनाने से रोकने का कोई तरीका नहीं है, इसलिए मुझे लगता है कि इसकी अनुपस्थिति के बजाय फ़ाइल के सकारात्मक अस्तित्व की जांच करना सबसे अच्छा है।

0

मुझे लगता है कि तुम क्या कह रहे हैं विशेष रूप से रेस स्थिति जहां है:

  1. फ़ाइल को खोलने पर
  2. संदर्भ चालू किया जाये और फ़ाइल हटा दी जाती है
  3. संदर्भ वापस चालू किया जाये और फ़ाइल आपरेशनों का प्रयास कर रहे हैं "खोला गया" फ़ाइल

इस मामले में जिस तरह से आप "संरक्षित" हैं, try ब्लॉक में सभी फ़ाइल हैंडलिंग कोड डालकर, किसी भी समय फ़ाइल पर आपके फ़ाइल ऑपरेशंस पहुंचने योग्य/भ्रष्ट हो जाते हैं catch ब्लॉक के माध्यम से "कृपापूर्वक" विफल हो पाएंगे। पाठ्यक्रम आधुनिक ओएस के

नोट इस वैसे भी ऐसा नहीं हो सकता, जब एक फ़ाइल "हटाए गए" है नष्ट नहीं होगी जब तक फाइल पर सभी खुले हैंडल हल कर रहे हैं (जारी)

+1

@downvoter - तर्क? क्या यहाँ कोई समस्या है? – Mike

संबंधित मुद्दे