2013-08-23 9 views
5

datamodel docs से संदर्भ प्रबंधकों पर फिर से ऊपर उठाने:एक अपवाद एक संदर्भ हैंडलर में

ध्यान दें कि __exit__() तरीकों से पारित कर दिया-इन अपवाद reraise नहीं होनी चाहिए; यह कॉलर की ज़िम्मेदारी है।


मैं एक अस्थायी फ़ाइल, जिसका फ़ाइल वर्णनकर्ता मैं close साथ लेकिन डिस्क के लिए कुछ भी लिखे बिना मुक्त करना चाहते हैं। मेरा सहज समाधान अपवाद को पारित करना था, लेकिन यह discouraged in the docs है - और निश्चित रूप से अच्छे कारणों से।

class Processor(object): 
    ... 
    def write(self, *args, **kwargs): 
     if something_bad_happens: 
      raise RuntimeError('This format expects %s columns: %s, got %s.' % (
           (len(self.cols), self.cols, len(args)))) 
     self.writer.writerow(args) 

    def __enter__(self): 
     return self 

    def __exit__(self, type, value, traceback): 
     # the RuntimeError from write will be set as type, value and so on .. 
     # I'd like to close the stream here (release the file descriptor), 
     # but I do not leave a trace of the associated file - 
     # (one can always 'manually' delete with `os.remove` but maybe there's a 
     # better way ..?) 
     self.output_pipe.close() 
इसके अलावा

मैं नहीं चाहता कि दो कारणों के लिए फोन करने वाले में इस विशेष मामले त्रुटि हैंडलिंग में हैं: कम से कम (नीचे देखें) फोन करने वाले में कोड रखने के लिए

  • फोन करने वाले खुश है अपवादों को छोड़कर (असफल तेजी से हम यहाँ चाहते है)

संदर्भ प्रबंधक कुछ इस तरह किया जाता है:

class Worker(object): 
    ... 
    def run(self): 
     # output setup so it will emit a three column CSV 
     with self.output().open('w') as output: 
      output.write('John', 'CA', 92101) 
      output.write('Jane', 'NY', 10304) 
      # should yield an error, since only three 'columns' are allowed 
      output.write('Hello', 'world') 

अद्यतन: नेस्टेड संदर्भ प्रबंधकों में, कैसे मैं सबसे बाहरी मुख्यमंत्री के लिए पर एक अपवाद पारित कर सकते हैं: मेरी quesion थोड़ा बीमार तैयार के रूप में मेरी समस्या वास्तव में इस के लिए नीचे उबला हुआ था?

+1

क्या आप वास्तव में '__exit__' में आउटपुट को दो बार बंद करना चाहते थे? – user2357112

+0

@ user2357112, वहां और कोड है जिसे मैंने यहां शामिल नहीं किया है - इसलिए कोड टेर्स और शायद संदर्भित करना मुश्किल हो सकता है, इसके लिए खेद है। मेरा प्रश्न अपडेट किया गया, मैं 'output_pipe' को दो बार बंद नहीं करता हूं। – miku

उत्तर

6
  • जब __exit__ सही लौटाता है, तो इसके लिए पारित कोई भी अपवाद निगल लिया जाता है।
  • जब __exit__ झूठा रिटर्न देता है, तो अपवाद का पुन: उपयोग किया जाता है।

def __exit__(self, type, value, traceback): 
    self.output_pipe.close() # always close the file 
    if type is not None: # an exception has occurred 
     os.unlink(...) # remove the file 
     return False  # reraise the exception 

आप निश्चित रूप से छोड़ सकता है return False अजगर के बाद से None वापस आ जाएगी (जो Falsish है) डिफ़ॉल्ट रूप से।


वैसे, self.output()Processor का एक उदाहरण है? यदि हां, तो

with self.output().open('w') as output: 

with self.output() as output: 

होना चाहिए किसी भी मामले में, यह अच्छा होगा यदि आप बाद सही सिंटैक्स होने के लिए व्यवस्था कर सकता है। आपको __enter__ को बदलना होगा:

def __enter__(self): 
    return self.output_pipe.open('w') 
+0

धन्यवाद, मुझे लगता है कि 'वापसी झूठी' बस मैं चाहता हूं कि मैं खोजूं। – miku

+1

@ मिकू: * कोई भी * झूठा मूल्य करेगा; 'कोई नहीं 'शामिल है; स्पष्ट रूप से लौटने का मतलब नहीं है 'कोई नहीं' वापस आ गया है और अपवाद बनी हुई है। –

+1

@MartijnPieters, मैं देखता हूं। मुझे इस समय स्पष्ट 'गलत' थोड़ा और पुनः प्राप्त करने योग्य लगता है। मुझे इस पर सम्मेलनों के लिए मानक पुस्तकालय की जांच करनी है ... – miku

2

नहीं को raise अपवाद की आवश्यकता है; अपवाद में पहले से ही उठाया गया है और आपके संदर्भ प्रबंधक को केवल इसके बारे में सूचित किया जा रहा है।

टेस्ट अगर वहाँ था कोई बजाय अपवाद:

if type is None: 
    # if no exception is raised, proceed as usual: 
    self.output_pipe.close() 

अपने संदर्भ प्रबंधक उस पल आप अपवाद को दबाने था पर True वापस आना था तो; फ़ंक्शन से बाहर निकलने के बजाय None लौटाता है और अपवाद 'उठाया' रहता है।

ध्यान दें कि tempfile module में दो प्रकार की अस्थायी फ़ाइल ऑब्जेक्ट्स शामिल हैं जो संदर्भ प्रबंधकों के रूप में कार्य करती हैं, जो प्लेटफ़ॉर्म से स्वतंत्र पहले से ही स्वयं को हटाती हैं। POSIX सिस्टम पर आप सृजन के बाद फ़ाइल को अनलिंक कर सकते हैं; फ़ाइल डिस्क्रिप्टर जीवित रहता है जब तक आप फ़ाइल बंद नहीं करते। विंडोज़ 'क्लोज़ ऑन क्लोज़' विकल्प भी प्रदान करता है। tempfile.NamedTemporaryFile() कक्षा आपके प्लेटफ़ॉर्म के लिए सही विकल्प का उपयोग करती है।

+0

यह अच्छा लग रहा है और मैं जो चाहता हूं वह करूँगा, लेकिन क्या यह 'output_pipe' के संसाधन (फ़ाइल डिस्क्रिप्टर) को मुक्त करता है जो उस समय' w' मोड में एक खुली फ़ाइल है? – miku

+0

बिल्कुल परीक्षण क्यों करें? – user2357112

+0

@ मिकू: ऐसा लगता है कि आपका कोड 'self.output_pipe.close() '** दो बार ** कहता है; दूसरी बार केवल जब आपको अपवाद नहीं मिला। मैंने केवल अपवादों को संभालने के तरीके को दिखाया। –

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