जाँच पहले बनाम अपवाद हैंडलिंग?


88

मैं "हेड फर्स्ट पायथन" पुस्तक के माध्यम से काम कर रहा हूं (यह इस वर्ष सीखने के लिए मेरी भाषा है) और मुझे एक खंड मिला जहां वे दो कोड तकनीकों के बारे में बहस करते हैं:
पहले बनाम अपवाद की जांच।

यहाँ पायथन कोड का एक नमूना है:

# Checking First
for eachLine in open("../../data/sketch.txt"):
    if eachLine.find(":") != -1:
        (role, lineSpoken) = eachLine.split(":",1)
        print("role=%(role)s lineSpoken=%(lineSpoken)s" % locals())

# Exception handling        
for eachLine in open("../../data/sketch.txt"):
    try:
        (role, lineSpoken) = eachLine.split(":",1)
        print("role=%(role)s lineSpoken=%(lineSpoken)s" % locals())
    except:
        pass

पहला उदाहरण .splitफ़ंक्शन में एक समस्या से सीधे संबंधित है। दूसरा केवल अपवाद हैंडलर को इससे निपटने देता है (और समस्या को अनदेखा करता है)।

वे किताब में तर्क देते हैं कि पहले चेक करने के बजाय अपवाद हैंडलिंग का उपयोग करें। तर्क यह है कि अपवाद कोड सभी त्रुटियों को पकड़ लेगा, जहां पहले जाँच केवल उन चीजों को पकड़ लेगी जिनके बारे में आप सोचते हैं (और आप कोने के मामलों को याद करते हैं)। मुझे पहले जांच करना सिखाया गया है, इसलिए मेरी अंतरंग वृत्ति ऐसा करने की थी, लेकिन उनका विचार दिलचस्प है। मैंने कभी भी मामलों से निपटने के लिए अपवाद हैंडलिंग का उपयोग करने के बारे में नहीं सोचा था।

आम तौर पर दोनों में से कौन बेहतर अभ्यास माना जाता है?


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

9
बस "फ़ाइल मौजूद चेक" जाल में गिर नहीं है। फ़ाइल मौजूद = फ़ाइल तक पहुँच गया है, या कि यह 10 एमएस यह मेरी फाइल ओपन कॉल, आदि को पाने के लिए ले जाता है में मौजूद होगा! Blogs.msdn.com/b/jaredpar/archive/2009/04/27/...
बिली ओनली

11
अन्य भाषाओं की तुलना में पायथन में अपवादों को अलग तरह से समझा जाता है। उदाहरण के लिए एक संग्रह के माध्यम से पुनरावृत्ति करने का तरीका है कि उस पर .next () कॉल करें जब तक कि वह एक अपवाद न फेंके।
वूहोइनटेड

4
@ emeraldcode.com यह पायथन के बारे में पूरी तरह सच नहीं है। मैं बारीकियों को नहीं जानता, लेकिन उस प्रतिमान के चारों ओर भाषा का निर्माण किया गया है, इसलिए अपवाद को फेंकना लगभग अन्य भाषाओं की तरह महंगा नहीं है।
इजाकाता

उस ने कहा, इस उदाहरण के लिए, मैं एक गार्ड स्टेटमेंट का उपयोग करता हूं: if -1 == eachLine.find(":"): continueफिर, शेष लूप का इंडेंट नहीं किया जाएगा।
इज़्काता

जवाबों:


68

.NET में, अपवादों के अति प्रयोग से बचना आम बात है। एक तर्क प्रदर्शन है: .NET में, एक अपवाद फेंकना कम्प्यूटेशनल रूप से महंगा है।

उनके अति प्रयोग से बचने का एक और कारण यह है कि कोड को पढ़ना बहुत मुश्किल हो सकता है जो उन पर बहुत अधिक निर्भर करता है। जोएल स्पोलस्की की ब्लॉग प्रविष्टि इस मुद्दे का वर्णन करने का एक अच्छा काम करती है।

तर्क के दिल में निम्नलिखित उद्धरण है:

तर्क यह है कि मैं अपवादों को "गोटो" से बेहतर नहीं मानता, 1960 के दशक से हानिकारक माना जाता है, इसमें वे एक बिंदु से दूसरे कोड पर एक अचानक छलांग लगाते हैं। वास्तव में वे गोटो की तुलना में काफी खराब हैं:

1. वे स्रोत कोड में अदृश्य हैं । कोड के एक ब्लॉक को देखते हुए, फ़ंक्शंस सहित जो अपवादों को फेंक या नहीं कर सकते हैं, यह देखने का कोई तरीका नहीं है कि अपवादों को कहाँ से और कहाँ से फेंका जा सकता है। इसका मतलब है कि यहां तक ​​कि सावधान कोड निरीक्षण संभावित बग को प्रकट नहीं करता है।

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

निजी तौर पर, मैं अपवादों को फेंक देता हूं जब मेरा कोड वह नहीं कर सकता जो वह करने के लिए अनुबंधित है। जब मैं अपनी प्रक्रिया सीमा के बाहर किसी चीज़ से निपटने के लिए, SOAP कॉल, डेटाबेस कॉल, फ़ाइल IO, या सिस्टम कॉल के उदाहरण के लिए उपयोग करने की कोशिश करता / करती हूं, तो मैं उसका उपयोग करता हूं। अन्यथा, मैं रक्षात्मक रूप से कोड करने का प्रयास करता हूं। यह एक कठिन और तेज़ नियम नहीं है, लेकिन यह एक सामान्य अभ्यास है।

स्कॉट हंसेलमैन यहां .NET में अपवादों के बारे में भी लिखते हैं । इस लेख में उन्होंने अपवादों के संबंध में अंगूठे के कई नियमों का वर्णन किया है। मेरा मनपसंद?

आपको उन चीजों के लिए अपवाद नहीं फेंकना चाहिए जो हर समय होती हैं। तब वे "अध्यादेश" होंगे।


5
यहां एक और बिंदु है: यदि अपवाद लॉगिंग को सक्षम किया गया है, तो यह केवल असाधारण स्थितियों के लिए अपवाद का उपयोग करने के लिए बेहतर है, अध्यादेशों के लिए नहीं। अन्यथा लॉग क्लैट हो जाएगा और वास्तविक त्रुटि-कारण कारणों को अस्पष्ट किया जाएगा।
रोंगोंग

2
अच्छा जवाब। ध्यान दें कि अपवादों में अधिकांश प्लेटफार्मों पर एक उच्च प्रदर्शन हिट है। हालाँकि, जैसा कि आपने अन्य उत्तर पर मेरी टिप्पणियों के साथ नोट किया होगा, किसी चीज़ को कैसे कोडित करना है, इसके लिए कंबल नियम तय करने के मामले में प्रदर्शन एक विचार नहीं है।
मटनज

1
स्कॉट हैनेलमैन का उद्धरण बेहतर "अति प्रयोग" की तुलना में अपवाद के प्रति .Net दृष्टिकोण का वर्णन करता है। प्रदर्शन का अक्सर उल्लेख किया जाता है, लेकिन असली तर्क इसका उलटा है कि आप अपवादों का उपयोग क्यों करते हैं - यह कोड को समझने में कठिन बनाता है और जब सामान्य स्थिति में अपवाद होता है, तो इससे निपटने के लिए। जोएल के लिए, बिंदु 1 वास्तव में एक सकारात्मक है (अदृश्य का मतलब है कि कोड दिखाता है कि यह क्या करता है, न कि यह क्या करता है), और बिंदु 2 अप्रासंगिक (आप पहले से ही एक असंगत स्थिति में हैं, या कोई अपवाद नहीं होना चाहिए) । फिर भी, +1 के लिए "वह नहीं कर सकता जो उसे करने के लिए कहा गया है"।
जमरनो

5
हालांकि इस सवाल का जवाब नेट के लिए ठीक है, यह बहुत नहीं है pythonic है, तो यह देखते हुए कि यह एक अजगर सवाल है, मैं देखना क्यों असफल है IVC के जवाब अधिक मतदान नहीं किया गया है।
मार्क बूथ

2
@IanGoldby: नहीं। अपवाद हैंडलिंग वास्तव में अपवाद पुनर्प्राप्ति के रूप में बेहतर वर्णित है। यदि आप एक अपवाद से उबर नहीं सकते हैं, तो संभवतः आपके पास कोई अपवाद हैंडलिंग कोड नहीं होना चाहिए। यदि विधि A कॉल विधि B, जो C, और C फेंकता है, की संभावना है, तो सबसे अधिक EITHER A OR B को पुनर्प्राप्त करना चाहिए, दोनों को नहीं। निर्णय "यदि मैं एक्स नहीं कर सकता हूं तो मैं वाई करूंगा" को टास्क खत्म करने के लिए किसी और की आवश्यकता होती है तो इससे बचना चाहिए। यदि आप कार्य पूरा नहीं कर सकते हैं, तो जो कुछ बचा है वह सफाई और लॉगिंग है। क्लीनअप इन .net ऑटोमैटिक होना चाहिए, लॉगिंग सेंट्रलाइज्ड होनी चाहिए।
jmoreno

78

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

हालांकि, नंगे except:बयानों के साथ-साथ बयानों को छोड़कर ओवरब्रॉड से सावधान रहें , क्योंकि वे दोनों भी बग को मुखौटा कर सकते हैं - कुछ इस तरह होगा:

for eachLine in open("../../data/sketch.txt"):
    try:
        role, lineSpoken = eachLine.split(":",1)
    except ValueError:
        pass
    else:
        print("role=%(role)s lineSpoken=%(lineSpoken)s" % locals())

8
एक .NET प्रोग्रामर के रूप में, मैं इस पर क्रिंग करता हूं। लेकिन फिर, आप लोग सब कुछ अजीब करते हैं। :)
फिल

यह असाधारण रूप से निराशाजनक है (जब तक कि इरादा न किया गया हो) जब एपीआई संगत नहीं होते हैं तो अपवाद किन परिस्थितियों में फेंके जाते हैं, या जब एक ही अपवाद प्रकार के तहत कई अलग-अलग प्रकार की विफलताओं को फेंक दिया जाता है।
जैक

तो आप अप्रत्याशित त्रुटियों और अपेक्षित प्रकार के रिटर्न मानों के लिए एक ही तंत्र का उपयोग करते हुए समाप्त होते हैं। यह एक नंबर के रूप में 0 का उपयोग करने के रूप में महान है, एक गलत बूल, और एक अवैध सूचक जो 128 + SIGSEGV के निकास कोड के साथ आपकी प्रक्रिया को छोड़ देगा, क्योंकि कितना सुविधाजनक है, आपको अब अलग-अलग चीजों की आवश्यकता नहीं है। स्पार्क की तरह! या पैर की उंगलियों के साथ जूते ...
योमन

2
@yeoman जब एक अपवाद फेंकने के लिए एक अलग सवाल है, यह एक "का अपवाद फेंकने के लिए निम्नलिखित संभावना है" के लिए एक सशर्त का उपयोग करने के बजाय try/ उपयोग करने के बारे में है except, और पायथन अभ्यास निश्चित रूप से पूर्व को पसंद करना है। यह इस बात पर चोट नहीं करता है कि दृष्टिकोण (शायद) यहां अधिक कुशल है, क्योंकि, उस मामले में जहां विभाजन सफल होता है, आप केवल एक बार स्ट्रिंग चलते हैं। जैसे कि क्या splitमुझे एक अपवाद फेंकना चाहिए, मैं कहूंगा कि यह निश्चित रूप से होना चाहिए - एक सामान्य नियम यह है कि जब आप अपना नाम कहते हैं तो आप ऐसा नहीं कर सकते हैं और आप एक लापता परिसीमन में विभाजित नहीं हो सकते।
lvc

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

27

एक व्यावहारिक दृष्टिकोण

आपको रक्षात्मक होना चाहिए लेकिन एक बिंदु पर। आपको अपवाद हैंडलिंग लिखना चाहिए लेकिन एक बिंदु तक। मैं एक उदाहरण के रूप में वेब प्रोग्रामिंग का उपयोग करने जा रहा हूं क्योंकि यह वह जगह है जहां मैं रहता हूं।

  1. मान लें कि सभी उपयोगकर्ता इनपुट खराब है और केवल डेटा प्रकार सत्यापन, पैटर्न चेक और दुर्भावनापूर्ण इंजेक्शन के बिंदु तक रक्षात्मक रूप से लिखते हैं। रक्षात्मक प्रोग्रामिंग ऐसी चीजें होनी चाहिए जो संभवतः बहुत बार हो सकती हैं जिन्हें आप नियंत्रित नहीं कर सकते हैं।
  2. नेटवर्क सेवाओं के लिए अपवाद संभालना लिखें जो कई बार विफल हो सकते हैं और उपयोगकर्ता प्रतिक्रिया के लिए इनायत से संभाल सकते हैं। अपवाद प्रोग्रामिंग का उपयोग नेटवर्क चीजों के लिए किया जाना चाहिए जो समय-समय पर विफल हो सकते हैं लेकिन आमतौर पर ठोस होते हैं और आपको अपने कार्यक्रम को काम करने की आवश्यकता होती है।
  3. इनपुट डेटा के मान्य होने के बाद अपने एप्लिकेशन के भीतर रक्षात्मक रूप से लिखने की जहमत न उठाएं। यह समय की बर्बादी है और आपके ऐप को फुला देता है। इसे उड़ा दें क्योंकि इसकी या तो कुछ बहुत ही दुर्लभ है जो संभालने के लायक नहीं है या इसका मतलब है कि आपको चरण 1 और 2 को अधिक ध्यान से देखने की आवश्यकता है।
  4. कभी भी अपने मूल कोड के अपवाद को न लिखें, जो किसी नेटवर्क डिवाइस पर निर्भर नहीं है। ऐसा करना खराब प्रोग्रामिंग और प्रदर्शन के लिए महंगा है। उदाहरण के लिए एक लूप में सीमा सरणी से बाहर होने की स्थिति में ट्राइ-कैच लिखने का मतलब है कि आपने लूप को पहले स्थान पर सही ढंग से प्रोग्राम नहीं किया था।
  5. सब कुछ केंद्रीय त्रुटि लॉगिंग द्वारा नियंत्रित किया जाना चाहिए जो उपरोक्त प्रक्रियाओं का पालन करने के बाद एक स्थान पर अपवादों को पकड़ता है। आप हर किनारे के मामले को नहीं पकड़ सकते क्योंकि यह अनंत हो सकता है, आपको केवल अपेक्षित कार्रवाई को संभालने वाले कोड लिखने की आवश्यकता है। इसलिए आप अंतिम उपाय के रूप में केंद्रीय त्रुटि हैंडलिंग का उपयोग करते हैं।
  6. TDD अच्छा है क्योंकि एक तरह से ब्लोट के बिना आपके लिए प्रयास करना है, जिसका अर्थ है कि आपको सामान्य ऑपरेशन का कुछ आश्वासन देना है।
  7. बोनस अंक एक कोड कवरेज टूल का उपयोग करना है उदाहरण के लिए इस्तांबुल नोड के लिए एक अच्छा है क्योंकि यह आपको दिखाता है कि आप परीक्षण नहीं कर रहे हैं।
  8. इस सब के लिए चेतावनी डेवलपर के अनुकूल अपवाद है । उदाहरण के लिए, यदि आप वाक्यविन्यास का गलत उपयोग करते हैं और क्यों समझाते हैं तो एक भाषा फेंकेगी। तो क्या आपकी उपयोगिता पुस्तकालयों को आपके कोड के थोक पर निर्भर करती है।

यह बड़े टीम परिदृश्यों में काम करने के अनुभव से है।

एक सादृश्य

सोचिए अगर आपने हर समय ISS के अंदर स्पेस सूट पहना हो। बाथरूम जाना या खाना बिल्कुल भी मुश्किल होगा। यह चारों ओर स्थानांतरित करने के लिए अंतरिक्ष मॉड्यूल के अंदर सुपर भारी होगा। यह चूसना होगा। आपके कोड के अंदर ट्राइ-कैच का एक गुच्छा लिखना उस तरह का है। आपके पास कुछ बिंदु होना चाहिए जहां आप कहते हैं, हे मैंने आईएसएस सुरक्षित कर लिया है और मेरे अंतरिक्ष यात्री अंदर ठीक हैं इसलिए हर परिदृश्य के लिए स्पेस सूट पहनना व्यावहारिक नहीं है जो संभवतः हो सकता है।


4
प्वाइंट 3 के साथ समस्या यह है कि यह कार्यक्रम को मानता है, और इस पर काम करने वाले प्रोग्रामर, एकदम सही हैं। वे नहीं हैं, इसलिए यह इन के साथ रक्षात्मक रूप से सबसे अच्छा कार्यक्रम है। मुख्य बिंदु पर मात्राओं को कम करना सॉफ्टवेयर को "यदि इनपुट्स की जाँच की गई है तो यह सही है" की तुलना में कहीं अधिक विश्वसनीय बना सकता है।
मटनज़

परीक्षण के लिए यही है।
जेसन सेब्रिंग

3
परीक्षण कोई पकड़ नहीं है। मुझे अभी तक एक परीक्षण सूट देखना है जिसमें 100% कोड और "पर्यावरण" कवरेज है।
मार्जन वेनमा

1
@emeraldcode: क्या आप मेरे साथ नौकरी चाहते हैं, मैं टीम में किसी को पसंद करूंगा जो हमेशा अपवाद के साथ, हर किनारे मामले के हर क्रमपरिवर्तन का परीक्षण करता है, जो सॉफ्टवेयर कभी भी निष्पादित करेगा। Abosoluite निश्चितता के साथ जानना अच्छा होना चाहिए कि आपका कोड पूरी तरह से परीक्षण किया गया है।
मटनज़

1
इस बात से सहमत। ऐसे परिदृश्य हैं जो रक्षात्मक प्रोग्रामिंग और अपवाद दोनों को संभालना अच्छी तरह से और खराब काम करते हैं, और हमें प्रोग्रामर को उन्हें पहचानना सीखना चाहिए, और उस तकनीक का चयन करना चाहिए जो सबसे उपयुक्त हो। मुझे प्वाइंट 3 पसंद है क्योंकि मेरा मानना ​​है कि हमें कोड के एक निश्चित स्तर पर यह मानने की आवश्यकता है, कि कुछ संदर्भ स्थितियों से संतुष्ट होना चाहिए। इन स्थितियों को कोड की बाहरी परत में रक्षात्मक रूप से कोडित करके संतुष्ट किया जाता है, और मुझे लगता है कि जब इन मान्यताओं को आंतरिक परत में तोड़ा जाता है तो अपवाद हैंडलिंग एक फिट है।
योबिन

15

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

मुझे लगता है कि यह कथन केवल बहुत विशिष्ट परिस्थितियों में सच है - जहां आउटपुट सही है, तो आपको परवाह नहीं है।

इसमें कोई संदेह नहीं है कि अपवादों को उठाना एक ध्वनि और सुरक्षित अभ्यास है। जब भी आपको लगे कि कार्यक्रम की वर्तमान स्थिति में ऐसा कुछ है जिसे आप (एक डेवलपर के रूप में) कर सकते हैं, या नहीं करना चाहते, तो आपको ऐसा करना चाहिए।

हालाँकि, आपका उदाहरण अपवादों को पकड़ने के बारे में है। यदि आप एक अपवाद को पकड़ते हैं, तो आप अपने आप को उन परिदृश्यों से बचा नहीं रहे हैं जिन्हें आप अनदेखा कर सकते हैं। आप ठीक इसके विपरीत कर रहे हैं: आप मानते हैं कि आपने इस प्रकार के अपवाद के कारण हो सकने वाले किसी भी परिदृश्य को अनदेखा नहीं किया है, और इसलिए आप आश्वस्त हैं कि इसे पकड़ना ठीक है (और इस प्रकार प्रोग्राम को बाहर निकलने से रोकें किसी भी अनकहा अपवाद के रूप में) होगा।

अपवाद दृष्टिकोण का उपयोग करते हुए, यदि आप ValueErrorअपवाद देखते हैं, तो आप एक पंक्ति छोड़ते हैं। पारंपरिक गैर-अपवाद दृष्टिकोण का उपयोग करते हुए, आप से लौटे मानों की संख्या की गणना करते हैं split, और यदि यह 2 से कम है, तो आप एक पंक्ति को छोड़ देते हैं। क्या आपको अपवाद दृष्टिकोण के साथ अधिक सुरक्षित महसूस करना चाहिए, क्योंकि आप अपनी पारंपरिक त्रुटि जांच में कुछ अन्य "त्रुटि" स्थितियों को भूल गए except ValueErrorहोंगे , और उन्हें आपके साथ पकड़ लेंगे?

यह आपके प्रोग्राम की प्रकृति पर निर्भर करता है।

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

यदि आप एक ऐसा एप्लिकेशन लिख रहे हैं जहाँ शुद्धता मायने रखती है (जैसे कि व्यवसाय या इंजीनियरिंग सॉफ़्टवेयर), तो यह एक भयानक दृष्टिकोण होगा। यदि आप किसी ऐसे परिदृश्य के बारे में भूल गए हैं ValueError, जो सबसे खराब है, तो आप जो सबसे बुरा काम कर सकते हैं, वह है इस अज्ञात परिदृश्य को चुपचाप अनदेखा करना और केवल रेखा को छोड़ना। यह बहुत ही सूक्ष्म और महंगा बग सॉफ्टवेयर में समाप्त होता है।

आप सोच सकते हैं ValueErrorकि इस कोड में आप एक ही रास्ता देख सकते हैं , यदि splitकेवल एक मान (दो के बजाय) वापस किया जाए। लेकिन क्या होगा अगर आपका printबयान बाद में ValueErrorकुछ शर्तों के तहत उठने वाली अभिव्यक्ति का उपयोग करना शुरू कर दे ? यह आपको कुछ पंक्तियों को छोड़ने का कारण बनेगा क्योंकि वे याद नहीं करते हैं :, लेकिन क्योंकि printउन पर विफल रहता है। यह एक सूक्ष्म बग का उदाहरण है जिसका मैं पहले उल्लेख कर रहा था - आप कुछ भी नोटिस नहीं करेंगे, बस कुछ लाइनें खो देंगे।

मेरी सिफारिश कोड को पकड़ने (लेकिन नहीं बढ़ाने!) से बचने के लिए है, जहां गलत आउटपुट का उत्पादन बाहर निकलने से भी बदतर है। इस तरह के कोड में अपवाद को पकड़ने का एकमात्र समय है जब मेरे पास वास्तव में तुच्छ अभिव्यक्ति है, इसलिए मैं आसानी से संभावित अपवाद प्रकारों में से प्रत्येक का कारण बन सकता हूं।

अपवादों के उपयोग के प्रदर्शन प्रभाव के रूप में, यह तुच्छ (पायथन में) है जब तक कि अपवाद अक्सर सामने नहीं आते हैं।

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

ये विचार केवल तभी मायने रखते हैं जब आप अक्सर विकृत सर्वर स्ट्रिंग्स को दूरस्थ सर्वरों को भेजते हैं या शून्य-मूल्यवान तर्क प्राप्त करते हैं जो आप विभाजन के लिए उपयोग करते हैं।

नोट: मेरा मानना ​​है कि आप except ValueErrorबस के बजाय उपयोग करेंगे except; जैसा कि अन्य लोगों ने बताया, और जैसा कि पुस्तक स्वयं कुछ पृष्ठों में कहती है, आपको कभी भी नंगे का उपयोग नहीं करना चाहिए except

एक और नोट: उचित गैर-अपवाद दृष्टिकोण के लिए splitखोज के बजाय, द्वारा लौटाए गए मूल्यों की संख्या की गणना करना है :। उत्तरार्द्ध बहुत धीमा है, क्योंकि यह द्वारा किए गए कार्य को दोहराता है splitऔर निष्पादन समय को लगभग दोगुना कर सकता है।


6

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


2

जो भी अच्छा काम करे उसका सदुपयोग करें ।।

  • कोड की पठनीयता और दक्षता के मामले में आपकी चुनी हुई प्रोग्रामिंग भाषा
  • आपकी टीम और सहमत कोड सम्मेलनों का सेट

अपवाद हैंडलिंग और रक्षात्मक प्रोग्रामिंग दोनों एक ही इरादे को व्यक्त करने के विभिन्न तरीके हैं।


0

यदि आप try/exceptमैकेनिक या ifस्टेटमेंट चेक का उपयोग करते हैं, तो टीबीएच, कोई फर्क नहीं पड़ता । आप आमतौर पर ईएएफपी और एलबीवाईएल दोनों को अधिकांश पायथन बेसलाइनों में देखते हैं, जिनमें ईएएफपी थोड़ा अधिक सामान्य है। EAFP कभी कभी है और अधिक पठनीय / मुहावरेदार है, लेकिन इस विशेष मामले में मुझे लगता है कि यह किसी भी तरह से ठीक है।

हालाँकि...

मैं आपके वर्तमान संदर्भ का उपयोग करके सावधान रहूंगा। उनके कोड के साथ कुछ चकाचौंध के मुद्दे:

  1. फ़ाइल डिस्क्रिप्टर लीक हो गया है। सीपीथॉन के आधुनिक संस्करण (एक विशिष्ट पायथन इंटरप्रेटर) वास्तव में इसे बंद कर देंगे, क्योंकि यह एक अनाम वस्तु है जो केवल लूप के दौरान दायरे में है (जीसी लूप के बाद इसे nuke होगा)। हालांकि, अन्य दुभाषियों के पास यह गारंटी नहीं है। वे वर्णनकर्ता को एकमुश्त लीक कर सकते हैं। withपायथन में फाइलें पढ़ते समय आप लगभग हमेशा मुहावरे का उपयोग करना चाहते हैं: बहुत कम अपवाद हैं। यह उनमें से एक नहीं है।
  2. पोकेमॉन अपवाद से निपटने में त्रुटि होती है क्योंकि यह त्रुटियों को मिटा देता है (अर्थात exceptएक विशिष्ट अपवाद को नहीं पकड़ता है)
  3. Nit: आप tuple unpacking के लिए parens की जरूरत नहीं है। बस कर सकते हैंrole, lineSpoken = eachLine.split(":",1)

Ivc के पास इस और EAFP के बारे में एक अच्छा जवाब है, लेकिन यह भी वर्णनकर्ता को लीक कर रहा है।

LBYL संस्करण आवश्यक रूप से EAFP संस्करण के रूप में प्रदर्शन करने वाला नहीं है, इसलिए यह कहना कि अपवाद फेंकना "प्रदर्शन के मामले में महंगा है" स्पष्ट रूप से गलत है। यह वास्तव में आपके द्वारा संसाधित किए जा रहे तार के प्रकार पर निर्भर करता है:

In [33]: def lbyl(lines):
    ...:     for line in lines:
    ...:         if line.find(":") != -1:
    ...:             # Nuke the parens, do tuple unpacking like an idiomatic Python dev.
    ...:             role, lineSpoken = line.split(":",1)
    ...:             # no print, since output is obnoxiously long with %timeit
    ...:

In [34]: def eafp(lines):
    ...:     for line in lines:
    ...:         try:
    ...:             # Nuke the parens, do tuple unpacking like an idiomatic Python dev.
    ...:             role, lineSpoken = eachLine.split(":",1)
    ...:             # no print, since output is obnoxiously long with %timeit
    ...:         except:
    ...:             pass
    ...:

In [35]: lines = ["abc:def", "onetwothree", "xyz:hij"]

In [36]: %timeit lbyl(lines)
100000 loops, best of 3: 1.96 µs per loop

In [37]: %timeit eafp(lines)
100000 loops, best of 3: 4.02 µs per loop

In [38]: lines = ["a"*100000 + ":" + "b", "onetwothree", "abconetwothree"*100]

In [39]: %timeit lbyl(lines)
10000 loops, best of 3: 119 µs per loop

In [40]: %timeit eafp(lines)
100000 loops, best of 3: 4.2 µs per loop

-4

मूल रूप से अपवाद हैंडलिंग OOP भाषाओं के लिए अधिक उपयुक्त माना जाता है।

दूसरा बिंदु प्रदर्शन है, क्योंकि आपको eachLine.findहर पंक्ति के लिए निष्पादित नहीं करना है ।


7
-1: कंबल नियमों का प्रदर्शन बेहद खराब कारण है।
मट्टनज़

3
नहीं, अपवाद पूरी तरह से OOP से असंबंधित हैं।
पॉबी

-6

मुझे लगता है कि रक्षात्मक प्रोग्रामिंग प्रदर्शन को नुकसान पहुंचाती है। आपको केवल उन अपवादों को भी पकड़ना चाहिए जिन्हें आप संभालने जा रहे हैं, आप जो भी संभालना नहीं जानते उसे अपवाद के साथ रनटाइम डील करें।


7
फिर भी पठनीयता पर प्रदर्शन के बारे में चिंता करने के लिए anotehr -1, रखरखाव के लिए bla bla bla। प्रदर्शन कोई कारण नहीं है।
मटनज़

क्या मुझे पता है कि आप बिना समझाए -1s बांटने के लिए क्यों भाग रहे हैं? डिफेंसिव प्रोग्रामिंग का अर्थ है कोड की अधिक लाइनें, जिसका अर्थ है खराब प्रदर्शन। किसी को भी नीचे स्कोर करने से पहले समझाने की परवाह है?
मनोज

3
@ मुंज: जब तक आपने एक प्रोफाइलर से मापा है और कोड के एक ब्लॉक को अस्वीकार्य रूप से धीमा पाया जाता है, प्रदर्शन से पहले पठनीयता और स्थिरता के लिए कोड।
डेनिथ

@Manoj ने इसके अलावा कहा कि कम कोड सार्वभौमिक रूप से डिबगिंग और रखरखाव पर काम करने के लिए कम है। किसी भी चीज़ के लिए डेवलपर समय पर हिट करना सही कोड बहुत अधिक है। मैं मान रहा हूं (मेरी तरह) आप सही कोड नहीं लिखते हैं, अगर मैं गलत हूं तो मुझे माफ कर दें।
मटनज़

2
लिंक के लिए धन्यवाद - दिलचस्प पढ़ें कि मुझे इसके साथ सहमत होना है, एक बिंदु पर ... एक जीवन महत्वपूर्ण प्रणाली पर काम करना, जैसा कि मैं करता हूं "सिस्टम ने स्टैक ट्रेस को मुद्रित किया है, इसलिए हम ठीक से जानते हैं कि क्यों उन 300 लोगों की अनावश्यक रूप से मृत्यु हो गई। .... "वास्तव में बहुत अच्छा नहीं जा रहा है साक्षी स्टैंड में। मुझे लगता है कि यह उन चीजों में से एक है जहां हर स्थिति की एक अलग प्रतिक्रिया है।
मटनज़
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.