2013-01-19 24 views
9
की दक्षता

संभव डुप्लिकेट:
Python FAQ: “How fast are exceptions?”अजगर - पकड़ा अपवाद

मैं पढ़ रहा है कि अजगर अपवाद के संबंध में एक "से अनुमति प्राप्त करने के बेहतर माफी की तलाश के लिए" दर्शन को लागू करता है याद । लेखक के मुताबिक, इसका मतलब है कि पाइथन कोड को बहुत से प्रयासों का उपयोग करना चाहिए - समय से पहले निर्धारित करने की कोशिश करने के बजाय क्लॉज को छोड़कर, अगर आप ऐसा कुछ करने वाले थे जो अपवाद का कारण बनता।

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

क्या यह अनावश्यक रूप से प्रयास करने के लिए अक्षम है - क्लॉज को छोड़कर जिसमें आप अपवाद की उम्मीद करते हैं और लगभग हर समय पकड़े जाते हैं?

यहां कोड है - यह उन वस्तुओं की जांच करने के लिए Django ORM का उपयोग कर रहा है जो उपयोगकर्ताओं को विभिन्न तृतीय पक्ष सामाजिक प्रदाताओं के साथ जोड़ते हैं।

try: 
    fb_social_auth = UserSocialAuth.objects.get(user=self, provider='facebook') 
    user_dict['facebook_id'] = fb_social_auth.uid 
except ObjectDoesNotExist: 
    user_dict['facebook_id'] = None 

try: 
    fs_social_auth = UserSocialAuth.objects.get(user=self, provider='foursquare') 
    user_dict['foursquare_id'] = fs_social_auth.uid 
except ObjectDoesNotExist: 
    user_dict['foursquare_id'] = None 

try: 
    tw_social_auth = UserSocialAuth.objects.get(user=self, provider='twitter') 
    user_dict['twitter_id'] = tw_social_auth.uid 
except ObjectDoesNotExist: 
    user_dict['twitter_id'] = None 

पहले एक शायद ही कभी अपवाद ले जाएगा के बाद से अभी हम लागू करने कर रहे हैं प्राथमिक विधि नए उपयोगकर्ताओं साइट में शामिल होने के लिए के रूप में "फेसबुक के साथ प्रवेश करें"। लेकिन, ट्विटर और फोरस्क्वेयर वैकल्पिक हैं, अगर वे दोस्तों या अनुयायियों को आयात करना चाहते हैं, और मुझे उम्मीद है कि ज्यादातर लोग नहीं करेंगे।

मैं इस तर्क को कोड करने के बेहतर तरीके के लिए खुला हूं।

+1

कोड का विशिष्ट उदाहरण क्या है? –

+1

"अनुमति मांगने से क्षमा मांगने के लिए बेहतर" लागू करना हर जगह जहां यह लागू होता है निश्चित रूप से सबसे अच्छा विचार नहीं है। इस पर विचार करें: यदि आप जानते हैं कि 'try..catch' के अंदर कोड को 95% कॉल में अपवाद उठाया गया है, तो आप इसे बेहतर ढंग से लिखेंगे। –

+1

एक कहानियां जो आसपास जाती है वह है "असाधारण मामलों के लिए अपवाद हैं"। मुझे लगता है कि यदि आप अधिकतर समय में अपवाद की उम्मीद कर रहे हैं, तो आप गलत तरीके से अपवादों का उपयोग कर रहे हैं। –

उत्तर

6

जब भी आप कोड करते हैं तो चिंता का संतुलन होता है: प्रदर्शन, पठनीयता, शुद्धता, विस्तारशीलता, रखरखाव, आदि दुर्भाग्यवश, इन दोनों दिशाओं में एक ही समय में कोड को बेहतर बनाना संभव नहीं है। उदाहरण के लिए तेज़ क्या हो सकता है उतना तेज़ नहीं हो सकता है।

पाइथन में try..except को प्रोत्साहित करने के कारणों में से एक कारण है क्योंकि आप अक्सर अपने कोड का उपयोग करने के सभी तरीकों की अपेक्षा नहीं कर सकते हैं, इसलिए यह जांचने के बजाय कि कोई विशिष्ट स्थिति मौजूद है या नहीं, यह किसी भी को पकड़ने के लिए अधिक सामान्य है त्रुटि का कुछ वर्ग जो उत्पन्न हो सकता है। इस प्रकार try..except आपके कोड को और अधिक पुन: प्रयोज्य बना सकता है।

हालांकि, यह भी सच है कि try..except धीमा है यदि except खंड अक्सर पहुंच रहा है।

क्या उस ब्लॉक को कोड करने का कोई तरीका है ताकि अपवाद नहीं उठाया जा सके और कोशिश की जा सके .. कम लगातार स्थिति को पकड़ने के अलावा?

या यदि नहीं, तो दक्षता के लिए, आप try..except का उपयोग न करने का चयन कर सकते हैं। प्रोग्रामिंग में कुछ कठिन और तेज़ नियम हैं। आपको अपनी चिंताओं के संतुलन के आधार पर अपना रास्ता चुनना होगा।

+0

+1 प्रोग्रामिंग में कुछ कठिन और तेज़ नियम हैं। :) –

+0

आईएमओ पर +1 स्थान। – jldupont

2

यदि आप इस फ़ंक्शन को गति के लिए अनुकूलित करने का प्रयास कर रहे हैं, तो आपको वास्तविक बाधा होने की संभावना पर ध्यान देना चाहिए। आपके तीन डेटाबेस प्रश्न, जिनमें से प्रत्येक ऑपरेटिंग सिस्टम को संदर्भ स्विच करने का कारण बनता है, लगभग निश्चित रूप से अपवाद को पकड़ने से अधिक परिमाण का क्रम लेता है।आप जितनी जल्दी संभव के रूप में कोड बनाना चाहते हैं, एक में सभी तीन डेटाबेस प्रश्नों के संयोजन से शुरू: वस्तुओं के माध्यम से

auth_objects = UserSocialAuth.objects.filter(user=self, provider__in=('facebook', 'foursquare', 'twitter')) 

और फिर पाश। provider__in फ़िल्टर अनावश्यक हो सकता है यदि उन तीन प्रदाताओं डेटाबेस में केवल एक ही हैं।

2

यह सच है कि अपवाद को पकड़ना मामूली महंगा है (कुछ समय के लिए नीचे देखें) और आप इसे अपने कार्यक्रम की बाधा में नहीं चाहते हैं, लेकिन आपके द्वारा दिए गए उदाहरणों में अपवाद को पकड़ने वाला है Model.objects.get पर कॉल के मुकाबले रनटाइम का एक बहुत छोटा हिस्सा जिसे SQL क्वेरी बनाना है, इसे डेटाबेस सर्वर पर भेजना है, और डेटाबेस को यह रिपोर्ट करने का इंतजार है कि ऐसी कोई वस्तु नहीं है।

कुछ उदाहरण समय। फंक्शन f2 एक अपवाद फेंकता है और पकड़ता है, जबकि f1 अपवादों का उपयोग किये बिना समान कार्यक्षमता लागू करता है। (ताकि

def f3(): 
    try: 
     MyModel.objects.get(id=999999) 
    except MyModel.DoesNotExist: 
     pass 

इस बारे में 400 बार f2 से अधिक समय लेता:

d = dict() 

def f1(): 
    if 0 in d: return d[0] 
    else: return None 

def f2(): 
    try: return d[0] 
    except KeyError: return None 

>>> timeit(f1) 
0.25134801864624023 
>>> timeit(f2) 
2.4589600563049316 

और f3 डेटाबेस से न के बराबर वस्तु Django के ORM के माध्यम से (जो एक ही मशीन पर चल रहा है) निकलने की कोशिश करता लंबे समय तक कि मैं डिफ़ॉल्ट number=1000000 पुनरावृत्तियों को पूरा करने के लिए इंतजार नहीं करना चाहता था):

>>> timeit(f3, number=1000) 
1.0703678131103516