2013-03-22 5 views
5

पृष्ठभूमि

मैं हाल ही में अजगर with कीवर्ड की खोज की और अधिक सुंदरता से कुछ परिदृश्यों जहां मैं पहले try: ... finally: ... निर्माणों का इस्तेमाल किया है चाहता हूँ से निपटने के लिए अपनी क्षमता उपयोगिता देखना शुरू किया। मैंने तुरंत लिखने वाले कुछ कोड में MySQLdb कनेक्शन ऑब्जेक्ट पर इसे आज़माने का निर्णय लिया।पायथन डेटाबेस एपीआई में निर्दिष्ट कनेक्शन ऑब्जेक्ट्स के लिए __enter__ और __exit__ व्यवहार है?

मैं कैसे __enter__ और अजगर डेटाबेस API का कार्यान्वयन करने में __exit__ व्यवहार, और भोलेपन से अपेक्षित व्यवहार फ़ाइल वस्तुओं की तरह होने के लिए पर पढ़ने के लिए परेशान नहीं किया - सब मैं उम्मीद कर रहा था था बाहर निकलने के connection.close() कॉल करने के लिए।

मेरे भ्रम की स्थिति की कल्पना कीजिए, फिर, इस व्यवहार पर:

>>> with util.get_db_connection() as conn: 
...  print conn 
... 
<MySQLdb.cursors.Cursor object at 0xb6ca8b4c> 

get_db_connection() एक MySQLdb कनेक्शन वस्तु देता है, लेकिन यह है कि कनेक्शन वस्तु के __enter__ विधि एक कर्सर वस्तु, नहीं कनेक्शन वस्तु ही देता है कि मैं उम्मीद कर रहा था दिए गए __enter__ और __exit__ फ़ाइल ऑब्जेक्ट्स के लिए काम करते हैं। मुझे लगता है कि मुझे with util.get_db_connection() as cursor: करना चाहिए, या अन्यथा with का उपयोग नहीं करना चाहिए।

प्रश्न

तुरंत इस खोज ने मुझे कुछ चीजें आश्चर्य बनाता है:

  1. और क्या MySQLdb कनेक्शन वस्तुओं करते __enter__ और __exit__ तरीकों करते हैं? __exit__ मेरे बिना जादुई रूप से प्रतिबद्ध या रोलबैक परिवर्तन करने जा रहा है मेरे बिना स्पष्ट रूप से ऐसा होने के लिए पूछ रहा है? क्या कोई और स्पष्ट नहीं है कि मुझे पता होना चाहिए?
  2. क्या यह व्यवहार पाइथन डेटाबेस API (जैसे sqlite3, django, या psycopg2) के अन्य कार्यान्वयन में समान है?
  3. क्या यह व्यवहार औपचारिक रूप से कहीं भी specced है? 'Enter', 'exit' और 'context manager' के लिए नवीनतम spec (PEP 249 -- Python Database API Specification v2.0) ctrl-f कुछ भी फेंक नहीं देता है।

उत्तर

15

पाइथन डीबीएपीआई को पाइथन भाषा में संदर्भ प्रबंधकों को जोड़ने से पहले अच्छी तरह से लिखा गया था।

इस प्रकार, विभिन्न डेटाबेस पुस्तकालयों ने संदर्भ प्रबंधक समर्थन को कार्यान्वित करने के तरीके पर अपने अपने निर्णय किए हैं (यदि उन्होंने इसे बिल्कुल लागू किया है)।

आमतौर पर डेटाबेस प्रबंधक का उपयोग कर संदर्भ प्रबंधक के रूप में आपको लेनदेन से जोड़ता है। लेनदेन __enter__ पर शुरू किया गया है, और गीलेर के आधार पर __exit__ पर प्रतिबद्ध या निरस्त किया गया है या नहीं अपवाद था। जैसे, आप अलग से जोड़ने के बाद एक संदर्भ प्रबंधक के रूप में MySQL कनेक्शन का उपयोग करने वाले हैं:

connection = util.get_db_connection() 

with connection as cursor: 
    cursor.execute(...) 

# connection commit is issued if no exceptions were raised. 

sqlite3 context manager implementation आसानी से अलग है; यह भी लेन-देन का प्रबंधन करता है, लेकिन __enter__ विधि से एक कर्सर वापस नहीं करता है:

con = sqlite3.connect(":memory:") 
with con: 
    cursor = con.cursor() 
    # or use the connection directly 
    con.execute(...) 

तकनीकी तौर पर, यह सिर्फ __enter__ पर self देता है।

+0

माईएसक्यूएल के लिए, मैं अक्सर संदर्भ प्रबंधक.क्लोसिंग (डीबी()) के साथ डी, डी के रूप में करता हूं: 'ऑटो-क्लोजिंग * और * लेनदेन प्राप्त करने के लिए। – glglgl

0

इस लिंक में __enter__ फ़ंक्शन देखें। https://github.com/PyMySQL/mysqlclient-python/blob/master/MySQLdb/connections.py

__enter__ कनेक्शन ऑब्जेक्ट रिटर्न का कार्य self.cursor()

यही कारण है कि आप कनेक्शन ऑब्जेक्ट के बजाय कर्सर ऑब्जेक्ट प्राप्त कर रहे हैं।

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