2009-06-10 5 views
6

मेरे पास एक आंतरिक डेटाबेस कनेक्शन वाला ऑब्जेक्ट है जो पूरे जीवनकाल में सक्रिय है। कार्यक्रम के अंत में, कनेक्शन को प्रतिबद्ध और बंद करना होगा। अब तक मैंने एक स्पष्ट close विधि का उपयोग किया है, लेकिन यह कुछ हद तक बोझिल है, खासकर जब कॉलिंग कोड में अपवाद हो सकते हैं।ऑब्जेक्ट विनाश पर एक आंतरिक pysqlite कनेक्शन की सफाई

मैं बंद करने के लिए __del__ विधि का उपयोग करने पर विचार कर रहा हूं, लेकिन कुछ पढ़ने के बाद मुझे चिंता है। क्या यह एक वैध उपयोग पैटर्न है? क्या मुझे यकीन है कि आंतरिक संसाधन __del__ में ठीक से मुक्त हो जाएंगे?

This discussion एक समान प्रश्न उठाया लेकिन कोई संतोषजनक उत्तर नहीं मिला। मैं एक स्पष्ट close विधि नहीं चाहता हूं, और with का उपयोग करना एक विकल्प नहीं है, क्योंकि मेरी ऑब्जेक्ट को ओपन-प्ले-क्लोज़ के रूप में उपयोग नहीं किया जाता है, लेकिन इसे किसी अन्य, बड़े ऑब्जेक्ट के सदस्य के रूप में रखा जाता है, जीयूआई में चलते समय इसका इस्तेमाल करता है।

सी ++ पूरी तरह से विनाशकारी काम कर रहा है जहां कोई सुरक्षित रूप से संसाधनों को मुक्त कर सकता है, इसलिए मुझे लगता है कि पाइथन के पास कुछ भी सहमत है। किसी कारण से ऐसा लगता है कि यह मामला नहीं है, और समुदाय में कई लोग __del__ के खिलाफ शपथ लेते हैं। फिर विकल्प क्या है?

उत्तर

5

आप के बाद से मॉड्यूल पूरे आवेदन में एक ही वस्तु रखने के एक कनेक्शन मॉड्यूल बना सकते हैं, और एक समारोह रजिस्टर atexit मॉड्यूल

# db.py: 
import sqlite3 
import atexit 

con = None 

def get_connection(): 
    global con 
    if not con: 
     con = sqlite3.connect('somedb.sqlite') 
    atexit.register(close_connection, con) 
    return con 

def close_connection(some_con): 
    some_con.commit() 
    some_con.close() 

# your_program.py 
import db 
con = db.get_connection() 
cur = con.cursor() 
cur.execute("SELECT ...") 

यह sugestion धारणा कनेक्शन पर आधारित है के साथ इसे बंद करने के लिए आपके आवेदन में एक उदाहरण (सिंगलटन) जैसा लगता है जो एक मॉड्यूल ग्लोबल अच्छी तरह से प्रदान करता है।

यदि ऐसा नहीं है, तो आप एक विनाशक का उपयोग कर सकते हैं।

हालांकि विनाशक कचरा कलेक्टरों और परिपत्र संदर्भों के साथ अच्छी तरह से नहीं जाते हैं (आपको विनाशक के नाम से पहले परिपत्र संदर्भ को हटा देना चाहिए) और यदि ऐसा नहीं है (आपको एकाधिक कनेक्शन की आवश्यकता है) तो आप विनाशक के लिए जा सकते हैं । बस परिपत्र संदर्भों को चारों ओर न रखें या आपको खुद को तोड़ना होगा।

इसके अलावा, आपने सी ++ के बारे में जो कहा वह गलत है। यदि आप सी ++ में विनाशकों का उपयोग करते हैं तो उन्हें या तो कॉल कहा जाता है जब ऑब्जेक्ट को परिभाषित करने वाला ब्लॉक समाप्त होता है (जैसे कि पाइथन with) या जब आप delete कीवर्ड का उपयोग करते हैं (जो new के साथ बनाए गए ऑब्जेक्ट को हटा देता है)। इसके बाहर आपको एक स्पष्ट close() का उपयोग करना चाहिए जो विनाशक नहीं है। तो यह सिर्फ अजगर की तरह है - अजगर भी "बेहतर" है क्योंकि इसमें एक कचरा कलेक्टर है।

+0

इस तरह के कनेक्शन का उपयोग करने वाले इंजेक्शन के लिए 'लीकी अबास्ट्रक्शन' तरीके में इस प्रकार का अवांछित नहीं है? मैं सिर्फ सी ++ में विनाशक का उपयोग क्यों नहीं कर सकता ?? –

+0

@ एलीबेन: यह कर सकता है। हालांकि विनाशक कचरा कलेक्टरों और परिपत्र संदर्भों के साथ अच्छी तरह से नहीं जाते हैं (आपको विनाशक कहने से पहले परिपत्र संदर्भ को स्वयं हटा देना चाहिए) और आपके आवेदन में कनेक्शन एक उदाहरण (सिंगलटन) जैसा लगता है जो एक मॉड्यूल ग्लोबल अच्छी तरह से प्रदान करता है। यदि ऐसा नहीं है (आपको एकाधिक कनेक्शन की आवश्यकता है) तो आप एक विनाशक के लिए जा सकते हैं। बस परिपत्र संदर्भों को चारों ओर न रखें या आपको खुद को तोड़ना होगा। – nosklo

+0

फिर सी ++ के विनाशक, ठीक नहीं। सही आरएआईआई के साथ कोडिंग, संसाधन के सूचक को एक स्मार्ट सूचक (शायद संदर्भित गिनती) के रूप में रखा जाएगा जो गिनती को स्वचालित रूप से 0 तक पहुंचने पर खुद को हटा दिया जाता है। हालांकि, इसके लिए अतिरिक्त मशीनरी (स्मार्ट पॉइंटर) के साथ-साथ –

6

with कथन पर पढ़ें। आप इसके उपयोग के मामले का वर्णन कर रहे हैं।

आपको with कथन द्वारा उपयोग की जाने वाली विधियों को __enter__ और __exit__ विधियों को संभालने वाले "संदर्भ प्रबंधक" वर्ग में अपना कनेक्शन लपेटने की आवश्यकता होगी।

अधिक जानकारी के लिए PEP 343 देखें।


संपादित

"मेरे उद्देश्य केवल के रूप में खुला खेलने-पास के रूप में इस्तेमाल नहीं कर रहा है, लेकिन एक और के एक सदस्य, बड़ा वस्तु के रूप में रखा जाता है"

class AnObjectWhichMustBeClosed(object): 
    def __enter__(self): 
     # acquire 
    def __exit__(self, type, value, traceback): 
     # release 
    def open(self, dbConnectionInfo): 
     # open the connection, updating the state for __exit__ to handle. 

class ALargerObject(object): 
    def __init__(self): 
     pass 
    def injectTheObjectThatMustBeClosed(self, anObject): 
     self.useThis = anObject 

class MyGuiApp(self): 
    def run(self): 
     # build GUI objects 
     large = ALargeObject() 
     with AnObjectWhichMustBeClosed() as x: 
      large.injectTheObjectThatMustBeClosed(x) 
      mainLoop() 

कुछ लोग इस "निर्भरता इंजेक्शन" और "नियंत्रण में उलझन" कहते हैं। अन्य लोग इसे रणनीति पैटर्न कहते हैं। "ऑब्जेक्टटैटमस्टबॉक्लोज्ड" एक रणनीति है, जो कुछ बड़ी वस्तु में प्लग है। असेंबली जीयूआई ऐप के शीर्ष-स्तर पर बनाई गई है, क्योंकि आमतौर पर डेटाबेस जैसे संसाधनों का अधिग्रहण किया जाता है।

+0

मैंने उल्लेख किया है कि मैं यहां 'साथ' उपयोग नहीं कर सकता, और समझाया कि सवाल में क्यों। क्या मैं कुछ भूल रहा हूँ? क्या आप समझा सकते हैं कि ऑब्जेक्ट को एक बड़ी जीयूआई-आधारित कक्षा में एक उदाहरण के रूप में आयोजित किया जाता है जो घटनाओं के आधार पर काम करता है? –

+0

@ एसएलॉट: क्या यह एक बग हो सकता है? मेरे प्रश्न में 4 अनुच्छेद हैं - तीसरा उल्लेख 'साथ' और जीयूआई –

+0

मूल रूप से, मुझे लगता है कि आपका समाधान कुछ हद तक अधिक है। कल्पना कीजिए कि मेरे पास ऐसी 10 वस्तुएं हैं जिन्हें बंद करने की आवश्यकता है ... मुझे बस एक विनाशक था !! –

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