सेटिंग
मुझे अक्सर यह निर्धारित करने में परेशानी होती है कि अपवाद का उपयोग कब और कैसे करना है। आइए एक सरल उदाहरण पर विचार करें: मान लें कि मैं एक वेबपेज को स्क्रैप कर रहा हूं, " http://www.abevigoda.com/ ", यह निर्धारित करने के लिए कि अबे विगोडा अभी भी जीवित है। ऐसा करने के लिए, हमें बस इतना करना होगा कि पेज डाउनलोड करें और बार देखें कि "अबे विगोडा" वाक्यांश दिखाई देता है। हम पहली उपस्थिति लौटाते हैं, क्योंकि इसमें अबे की स्थिति शामिल है। वैचारिक रूप से, यह इस तरह दिखेगा:
def get_abe_status(url):
# download the page
page = download_page(url)
# get all mentions of Abe Vigoda
hits = page.find_all_mentions("Abe Vigoda")
# parse the first hit for his status
status = parse_abe_status(hits[0])
# he's either alive or dead
return status == "alive"
जहां parse_abe_status(s)
"अबे विगोडा कुछ है " के रूप में एक स्ट्रिंग लेता है और " कुछ " भाग वापस करता है ।
इससे पहले कि आप तर्क दें कि अबे की स्थिति के लिए इस पृष्ठ को स्क्रैप करने के बहुत बेहतर और अधिक मजबूत तरीके हैं, याद रखें कि यह एक सामान्य स्थिति को उजागर करने के लिए उपयोग किया जाने वाला एक सरल और वंचित उदाहरण है।
अब, यह कोड समस्याओं का सामना कहाँ कर सकता है? अन्य त्रुटियों में, कुछ "अपेक्षित" हैं:
download_page
पृष्ठ को डाउनलोड करने में सक्षम नहीं हो सकता है, और एक फेंकता हैIOError
।- URL सही पृष्ठ पर इंगित नहीं हो सकता है, या पृष्ठ गलत तरीके से डाउनलोड किया गया है, और इसलिए कोई हिट नहीं है।
hits
खाली सूची है, फिर। - वेब पेज को बदल दिया गया है, संभवतः पेज के बारे में हमारी धारणा गलत है। शायद हम अबे विगोडा के 4 उल्लेखों की उम्मीद करते हैं, लेकिन अब हम 5 पाते हैं।
- कुछ कारणों से,
hits[0]
"अबे विगोडा कुछ है " फॉर्म का एक तार नहीं हो सकता है , और इसलिए इसे सही ढंग से पार्स नहीं किया जा सकता है।
पहला मामला वास्तव में मेरे लिए कोई समस्या नहीं है: एक IOError
फेंक दिया गया है और मेरे फ़ंक्शन के कॉलर द्वारा नियंत्रित किया जा सकता है। तो आइए अन्य मामलों पर विचार करें और मैं उन्हें कैसे संभाल सकता हूं। लेकिन पहले, मान लें कि हम parse_abe_status
संभव तरीके से मूर्खतापूर्ण तरीके से लागू करते हैं:
def parse_abe_status(s):
return s[13:]
अर्थात्, यह किसी भी त्रुटि की जाँच नहीं करता है। अब, विकल्पों पर:
विकल्प 1: वापसी None
मैं फोन करने वाले को बता सकता हूं कि कुछ गलत हो गया था None
:
def get_abe_status(url):
# download the page
page = download_page(url)
# get all mentions of Abe Vigoda
hits = page.find_all_mentions("Abe Vigoda")
if not hits:
return None
# parse the first hit for his status
status = parse_abe_status(hits[0])
# he's either alive or dead
return status == "alive"
यदि कॉल करने वाले को None
मेरे कार्य से प्राप्त होता है, तो उसे यह मान लेना चाहिए कि अबे विगोडा का कोई उल्लेख नहीं था, और इसलिए कुछ गलत हुआ। लेकिन यह बहुत अस्पष्ट है, है ना? और यह उस मामले में मदद नहीं करता है जहां hits[0]
हमने सोचा नहीं था कि यह क्या था।
दूसरी ओर, हम कुछ अपवादों में रख सकते हैं:
विकल्प 2: अपवादों का उपयोग करना
यदि hits
हम खाली हैं, IndexError
तो जब हम प्रयास करेंगे तो फेंक दिया जाएगा hits[0]
। लेकिन फोन करने वाले से यह अपेक्षा नहीं की जानी चाहिए कि IndexError
वह मेरे फंक्शन द्वारा फेंके गए हैंडल को संभाल सके , क्योंकि उसे पता नहीं है कि वह कहाँ IndexError
से आया है; यह find_all_mentions
सभी के लिए, वह जानता है , द्वारा फेंका जा सकता था । तो हम इसे संभालने के लिए एक कस्टम अपवाद क्लास बनाएंगे:
class NotFoundError(Exception):
"""Throw this when something can't be found on a page."""
def get_abe_status(url):
# download the page
page = download_page(url)
# get all mentions of Abe Vigoda
hits = page.find_all_mentions("Abe Vigoda")
try:
hits[0]
except IndexError:
raise NotFoundError("No mentions found.")
# parse the first hit for his status
status = parse_abe_status(hits[0])
# he's either alive or dead
return status == "alive"
अब क्या होगा अगर पेज बदल गया है और अप्रत्याशित संख्या में हिट हैं? यह भयावह नहीं है, क्योंकि कोड अभी भी काम कर सकता है, लेकिन एक कॉलर अतिरिक्त सावधानी बरतना चाहता है , या वह चेतावनी देना चाहता हो सकता है। तो मैं एक चेतावनी फेंक दूंगा:
class NotFoundError(Exception):
"""Throw this when something can't be found on a page."""
def get_abe_status(url):
# download the page
page = download_page(url)
# get all mentions of Abe Vigoda
hits = page.find_all_mentions("Abe Vigoda")
try:
hits[0]
except IndexError:
raise NotFoundError("No mentions found.")
# say we expect four hits...
if len(hits) != 4:
raise Warning("An unexpected number of hits.")
logger.warning("An unexpected number of hits.")
# parse the first hit for his status
status = parse_abe_status(hits[0])
# he's either alive or dead
return status == "alive"
अंत में, हम पा सकते हैं कि status
या तो जीवित या मृत नहीं है। हो सकता है, किसी अजीब कारण से, आज यह हो गया comatose
। तब मैं वापस नहीं लौटना चाहता False
, क्योंकि इसका मतलब है कि अबे मर चुका है। मुझे यहां क्या करना चाहिए? एक अपवाद फेंको, शायद। लेकिन किस तरह का? क्या मुझे एक कस्टम अपवाद वर्ग बनाना चाहिए?
class NotFoundError(Exception):
"""Throw this when something can't be found on a page."""
def get_abe_status(url):
# download the page
page = download_page(url)
# get all mentions of Abe Vigoda
hits = page.find_all_mentions("Abe Vigoda")
try:
hits[0]
except IndexError:
raise NotFoundError("No mentions found.")
# say we expect four hits...
if len(hits) != 4:
raise Warning("An unexpected number of hits.")
logger.warning("An unexpected number of hits.")
# parse the first hit for his status
status = parse_abe_status(hits[0])
if status not in ['alive', 'dead']:
raise SomeTypeOfError("Status is an unexpected value.")
# he's either alive or dead
return status == "alive"
विकल्प 3: कहीं बीच में
मुझे लगता है कि अपवादों के साथ दूसरी विधि, बेहतर है, लेकिन मुझे यकीन नहीं है कि मैं अपवादों का सही तरीके से उपयोग कर रहा हूं। मैं यह देखने के लिए उत्सुक हूं कि अधिक अनुभवी प्रोग्रामर इसे कैसे संभालेंगे।