2013-06-04 5 views
21

मैं एक with ब्लॉक में डेटाबेस लेनदेन के लिए तर्क संपुटित करने के लिए देख रहा हूँ; एक लेनदेन में कोड लपेटना और विभिन्न अपवादों को संभालना (मुद्दों को लॉक करना)। यह काफी आसान है, हालांकि मैं कुछ अपवादों के बाद ब्लॉक ब्लॉक को पुनः लोड करने के लिए ब्लॉक को भी समाहित करना चाहता हूं। मैं संदर्भ प्रबंधक में इसे अच्छी तरह से पैकेज करने का कोई तरीका नहीं देख सकता।`with` ब्लॉक में encapsulating पुनर्प्रयास

क्या with कथन के भीतर कोड दोहराना संभव है?

मैं इसे जो वास्तव में साफ है, इस के रूप में के रूप में बस का उपयोग करना चाहते हैं।

def do_work(): 
    ... 
    # This is ideal! 
    with transaction(retries=3): 
     # Atomic DB statements 
     ... 
    ... 

मैं वर्तमान में एक डेकोरेटर के साथ इस से निपटने हूँ, लेकिन मैं संदर्भ प्रबंधक (या दोनों वास्तव में), तो मैं बजाय with ब्लॉक में कोड की कुछ लाइनें रैप करने के लिए चुन सकते हैं की पेशकश करना पसंद करते हैं एक इनलाइन समारोह एक डेकोरेटर में लिपटे है, जो है जो मैं इस समय कर की:

with transaction(_perform_in_transaction, retries=3) as _perf: 
    _perf() 

के लिए:

def do_work(): 
    ... 
    # This is not ideal! 
    @transaction(retries=3) 
    def _perform_in_transaction(): 
     # Atomic DB statements 
     ... 
    _perform_in_transaction() 
    ... 
+0

http://docs.python.org/release/2.5/whatsnew/pep-343.html ऐसा लगता है कि संदर्भ प्रबंधक को कार्यान्वित करने के तरीके के उदाहरण हैं। – Vlad

उत्तर

4

सज्जाकार के रूप में सिर्फ खुद को काम करता हैं, तो आपको निम्न कर सकता है विवरण, आप transaction() एक कारखाने विधि है कि मूल विधि कॉल और विफलता पर कई बार retries नंबर करने के लिए इसे दोहराने के लिए सेट __callable__() के साथ एक वस्तु के रूप में रिटर्न लागू करने की आवश्यकता होगी; __enter__() और __exit__() डेटाबेस लेनदेन संदर्भ प्रबंधकों के लिए सामान्य के रूप में परिभाषित किया जाएगा।

आप वैकल्पिक रूप से transaction() स्थापित कर सकते हैं जैसे कि यह स्वयं को retries तक पारित विधि को निष्पादित करता है, जो शायद संदर्भ प्रबंधक को कार्यान्वित करने के समान काम की आवश्यकता होगी लेकिन इसका मतलब होगा कि वास्तविक उपयोग केवल घट जाएगा transaction(_perform_in_transaction, retries=3) (जो वास्तव में, सजावटी उदाहरण डेलनान के बराबर है)।

12

क्या with कथन के भीतर कोड दोहराना संभव है?

No.

के रूप में है कि मेलिंग सूची धागा में पहले ने कहा, आप डेकोरेटर पारित कर दिया फ़ंक्शन को कॉल करके दोहराव का एक सा कम कर सकते हैं:

def do_work(): 
    ... 
    # This is not ideal! 
    @transaction(retries=3) 
    def _perform_in_transaction(): 
     # Atomic DB statements 
     ... 
    # called implicitly 
    ... 
+0

आह, शर्म की बात है कि यह समर्थित नहीं है। धागे के लिंक के लिए धन्यवाद। मुझे क्लीनर बनाने के लिए कॉल को अंतर्निहित करने का विचार पसंद है। मैं सेट/'_perform_in_transaction' भीतर वार्स संशोधित करने के लिए चाहते हैं, तो मुझे लगता है कि मैं इसे मैन्युअल वैसे भी कहते हैं और वापसी क्या मैं' do_work' समारोह के बाकी जारी रखने की आवश्यकता करना होगा। –

4

तरीका है कि मेरे पास होता है यह एक मानक डेटाबेस लेनदेन context manager लागू है, लेकिन यह निर्माता में एक retries तर्क लेने के लिए अनुमति देने के लिए बस है क्या करना है। तो मैं बस इसे अपने विधि कार्यान्वयन में लपेटूंगा। इस तरह कुछ:

class transaction(object): 
    def __init__(self, retries=0): 
     self.retries = retries 
    def __enter__(self): 
     return self 
    def __exit__(self, exc_type, exc_val, traceback): 
     pass 

    # Implementation... 
    def execute(self, query): 
     err = None 
     for _ in range(self.retries): 
      try: 
       return self._cursor.execute(query) 
      except Exception as e: 
       err = e # probably ought to save all errors, but hey 
     raise err 

with transaction(retries=3) as cursor: 
    cursor.execute('BLAH') 
+1

क्या आप विस्तृत कर सकते हैं कि 'self._cursor' में' _cursor' कहां से आता है? –

+0

@ माइकमुलर मैं कुछ सामान्य डेटाबेस एपीआई रीति-रिवाजों पर कार्यान्वयन विवरणों में फंसने के बिना खींचने की कोशिश कर रहा हूं।'_cursor' का मतलब है [' कर्सर'] (http://www.python.org/dev/peps/pep-0249/#cursor-objects) ऑब्जेक्ट, जो विशेष डेटाबेस कनेक्शन के लिए उचित है। वास्तव में डेटाबेस लेनदेन करने के लिए, एक पूर्ण कार्यान्वयन को किसी प्रकार की 'कनेक्शन' ऑब्जेक्ट बनाने और रखने की आवश्यकता होगी। –

+0

@ हेनरीकेलर मैंने कुछ 'डी __init __ (स्वयं, कर्सर, retries = 0):' और '__init__'' के अंदर यह 'self._cursor = कर्सर' किया होगा। उपयोग: 'कर्सर के रूप में लेनदेन (कर्सर, retries = 3) के साथ:'। इसका कोई मतलब भी है क्या? –

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