2012-06-10 5 views
7

मैं एक अस्थायी निर्देशिका के साथ काम कर रहा हूं और मैं यह सुनिश्चित करना चाहता हूं कि यह प्रोग्राम बंद हो जाए (चाहे कार्यक्रम सफल हुआ हो)। मैं निर्देशिका बनाने में tempfile.mkdtemp उपयोग कर रहा हूँ और उस str का एक उपवर्ग में बनने वाले स्ट्रिंग है कि इसके __del__ आदेश पर निर्देशिका हटाता डाल:आप एक अस्थायी निर्देशिका का प्रबंधन कैसे करते हैं जैसे कि इसे प्रोग्राम पर बंद होने की गारंटी है?

import shutil 
import tempfile 

class TempDir(str): 
    """ container for temporary directory. 
    Deletes directory when garbage collected/zero references """ 
    def __del__(self): 
     shutil.rmtree(self.__str__(), onerror=my_error_fn) 

dbdir = TempDir(tempfile.mkdtemp()) 

यहाँ क्या मुझे यकीन है कि के बारे में नहीं कर रहा हूँ: या यदि प्रोग्राम बंद कर देता है एक कीबोर्ड इंटरप्ट होता है, क्या पाइथन स्वचालित रूप से सभी चरों को एकत्रित/कचरा हटा देगा? यदि नहीं, तो मैं यह कैसे सुनिश्चित कर सकता हूं कि निर्देशिका हटा दी जाए?

creating destructor methods in Python के बारे में संबंधित जानकारी। ऐसा लगता है कि TempDir ऑब्जेक्ट किसी अन्य संदर्भ का संदर्भ नहीं देता है, __del__ का उपयोग करके इसे ठीक करना चाहिए।

+1

आपने इसका परीक्षण कब किया है? क्या हर बार Ctrl + C '__del__' निष्पादित करता है? –

+0

ठीक है, बस मेरे परीक्षण के परिणाम जोड़े गए - सुझाव @ जोएल कॉर्नेट के लिए बहुत बहुत धन्यवाद! –

+0

'__del__' के अतिरिक्त' atexit' मॉड्यूल का उपयोग करने पर विचार करें। – martineau

उत्तर

17

मैं __del__ विधि का उपयोग नहीं करता, अर्थशास्त्र अविश्वसनीय है, और कचरा संग्रह में हस्तक्षेप कर सकता है। एक संदर्भ प्रबंधक का प्रयोग करें: __enter__ और __exit__ विधि को परिभाषित करें, और ऑब्जेक्ट का उपयोग with कथन में रखें। यह स्पष्ट है, यह स्पष्ट है, और यह चिंता के बिना काम करेगा।

या, एक संदर्भ प्रबंधक बनाने के लिए एक और तरीका:

@contextlib.contextmanager 
def tempdir(prefix='tmp'): 
    """A context manager for creating and then deleting a temporary directory.""" 
    tmpdir = tempfile.mkdtemp(prefix=prefix) 
    try: 
     yield tmpdir 
    finally: 
     shutil.rmtree(tmpdir) 
+1

इस बारे में प्रश्न: मैं इस निर्देशिका का उपयोग कई फाइलें बनाने के लिए करना चाहता हूं और फिर इसे केवल हटाएं: (1) जब प्रोग्राम समाप्त होता है या (2) जब निर्देशिका में फ़ाइलों के सभी संदर्भ चले जाते हैं (जिसका अर्थ है कि, मेरा कार्यान्वयन, TempDir कक्षा के सभी संदर्भ भी चले जाएंगे।) क्या यह प्रारूप ऐसा करने में सक्षम होगा? –

+1

मुझे लगता है कि यहां एक अतिरिक्त बिंदु है: यह वास्तव में केवल एक कथन में इसका उपयोग करने के लिए काम नहीं करता है - पैकेज का उपयोग करने वाले लोग मैनिपुलेटिंग करने जा रहे हैं, फाइलों को जोड़ना/निकालना और अस्थायी फ़ाइलों को पारदर्शी होना चाहिए। ऐसा लगता है कि यह संदर्भ प्रबंधक के लिए एक अच्छा फिट नहीं है। –

+0

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

1

यह प्रोग्राम समाप्त होने पर ही सब कुछ हटा देता है (जैसा कि सामान्य रूप से होता है)।

समझाने के लिए, यहाँ कोड मैं प्रयोग किया जाता है:

import tempfile 
import shutil 
import os 

class TempDir(str): 
    """ container for temporary directory. Deletes directory when garbage 
    collected/zero references """ 
    def __del__(self): 
     print "deleting temporary files in directory {}".format(self.__str__()) 
     shutil.rmtree(self.__str__(), onerror=delete_dir_handler) 

def delete_dir_handler(listdir_fn, dirname, exception): 
    try: 
     for fileobj in listdir_fn(dirname): 
      os.remove(fileobj) 
     os.removedirs(dirname) 
    except (AttributeError, OSError, TypeError): 
     print exception[1] 
     print "Sorry. Couldn't delete directory {}.".format(dirname) 
     raise 

test = TempDir(tempfile.mkdtemp()) 

और उत्पादन:

$ python my_file.py 
deleting temporary files in directory /var/folders/A9/A9xrfjrXGsq9Cf0eD2jf0U+++TI/-Tmp-/tmpG3h1qD 

आप इंटरैक्टिव मोड में चलाते हैं, तो यह जब तक आप इस कार्यक्रम से बाहर निकलने नहीं हटाता है।

$ python -i my program 
>>> # pressed Ctrl-C here 
KeyboardInterrupt 
>>> # again, Ctrl-C 
KeyboardInterrupt 
>>> # Ctrl-D to exit 
deleting temporary files in directory /var/folders/A9/A9xrfjrXGsq9Cf0eD2jf0U+++TI/-Tmp-/tmpMBGt5n 

अंत में, यदि आप फाइल करने के लिए एक raw_input('') लाइन जोड़ने के लिए, यह कार्यक्रम अंत के रूप में बिल्कुल वैसा ही व्यवहार करते हैं अगर आप CTRL-C दबाएं होगा।

7

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

__del__ का उपयोग आवेदन निकास पर मेरे अनुभव में अविश्वसनीय है। और संदर्भ प्रबंधक का उपयोग करने से यह सुनिश्चित करने के लिए परीक्षण फ़ाइलों को फिर से लिखना होगा कि सबकुछ अच्छी तरह से लपेटता है। इसके बजाय मैं atexit का उपयोग करता हूं। <package>.tests.__init__ में मैं सिर्फ कहा:

import atexit, shutil, tempfile 

test_area = tempfile.mkdtemp() 
atexit.register(shutil.rmtree, test_area) 

अजगर फिर बाहर निकलें पर shutil.rmtree(test_area) कॉल करेंगे। यदि आवश्यक हो तो त्रुटि प्रबंधन के लिए कीवर्ड तर्क भी जोड़े जा सकते हैं।

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