पायथन में खराब / अवैध तर्क संयोजनों पर मुझे किस अपवाद को उठाना चाहिए?


542

मैं पायथन में अमान्य तर्क संयोजनों को इंगित करने के लिए सर्वोत्तम प्रथाओं के बारे में सोच रहा था। मैं कुछ स्थितियों में आया हूँ जहाँ आपके पास एक समारोह है जैसे:

def import_to_orm(name, save=False, recurse=False):
    """
    :param name: Name of some external entity to import.
    :param save: Save the ORM object before returning.
    :param recurse: Attempt to import associated objects as well. Because you
        need the original object to have a key to relate to, save must be
        `True` for recurse to be `True`.
    :raise BadValueError: If `recurse and not save`.
    :return: The ORM object.
    """
    pass

इसके साथ एकमात्र झुंझलाहट यह है कि हर पैकेज का अपना, आमतौर पर थोड़ा अलग होता है BadValueError। मुझे पता है कि जावा में मौजूद है java.lang.IllegalArgumentException- क्या यह अच्छी तरह से समझा जाता है कि हर कोई BadValueErrorपायथन में अपना स्वयं का निर्माण करेगा या कोई अन्य, पसंदीदा तरीका है?

जवाबों:


608

जब तक आपको अधिक विशिष्ट अपवाद की आवश्यकता नहीं होगी, मैं सिर्फ ValueError बढ़ाऊंगा

def import_to_orm(name, save=False, recurse=False):
    if recurse and not save:
        raise ValueError("save must be True if recurse is True")

ऐसा करने का वास्तव में कोई मतलब नहीं है class BadValueError(ValueError):pass- आपका कस्टम वर्ग ValueError के उपयोग में समान है , इसलिए इसका उपयोग क्यों नहीं किया जाता है?


65
> "तो उसका उपयोग क्यों नहीं किया?" - विशिष्टता। शायद मैं किसी बाहरी परत "MyValueError" को पकड़ना चाहता हूं, लेकिन कोई भी / सभी "ValueError" नहीं।
केविन लिटिल

7
हाँ, विशिष्टता के सवाल का एक और हिस्सा है जहाँ ValueError को उठाया जाता है। यदि कैली फंक्शन आपके तर्कों को पसंद करता है, लेकिन math.sqrt को कॉल करता है (-1) आंतरिक रूप से, एक कॉलर पकड़ सकता है ValueError को उम्मीद है कि उसके तर्क अनुचित थे। शायद आप इस मामले में केवल संदेश की जांच करें ...
cdleary

3
मुझे यकीन नहीं है कि तर्क रखता है: अगर कोई बुला रहा है math.sqrt(-1), तो यह एक प्रोग्रामिंग त्रुटि है जिसे वैसे भी ठीक करने की आवश्यकता है। ValueErrorसामान्य कार्यक्रम निष्पादन में पकड़े जाने का इरादा नहीं है या यह व्युत्पन्न होगा RuntimeError
--रॉन

2
यदि त्रुटि तर्कों की संख्या पर है, तो एक फ़ंक्शन के लिए तर्कों की एक चर संख्या के साथ ... उदाहरण के लिए एक फ़ंक्शन जहां तर्कों को तर्कों की एक समान संख्या होनी चाहिए, फिर आपको सुसंगत होने के लिए TypeError को उठाना चाहिए। और अपनी खुद की कक्षा न बनाएं जब तक कि आपके पास) का उपयोग मामला न हो या बी) आप दूसरों द्वारा उपयोग किए जाने वाले पुस्तकालय का निर्यात कर रहे हैं। समय से पहले की कार्यक्षमता कोड की मृत्यु है।
एरिक एरोनसिटी

104

मुझे विरासत से मिलेगा ValueError

class IllegalArgumentError(ValueError):
    pass

कभी-कभी अपना खुद का अपवाद बनाना बेहतर होता है, लेकिन अंतर्निहित एक से विरासत में मिला, जो जितना संभव हो उतना करीब है।

यदि आपको उस विशिष्ट त्रुटि को पकड़ने की आवश्यकता है, तो एक नाम होना उपयोगी है।


26
लेखन कक्षाएं और कस्टम अपवाद लिखना बंद करें - pyvideo.org/video/880/stop-writing-classes
Hamish Grubijan

40
@ HamishGrubijan वह वीडियो भयानक है। जब किसी ने कक्षा के अच्छे उपयोग का सुझाव दिया, तो उसने कहा कि "कक्षाओं का उपयोग न करें।" प्रतिभाशाली। कक्षाएं अच्छी हैं। लेकिन इसके लिए मेरा शब्द न लें
रोब ग्रांट

12
@RobertGrant नहीं, आपको नहीं मिला। वह वीडियो वास्तव में "कक्षाओं का उपयोग न करें" के बारे में वास्तव में नहीं है। यह अधिक जटिल चीजों के बारे में नहीं है।
रायलू

15
@RayLuo में आप विवेक-जाँच कर सकते हैं कि वीडियो क्या कह रहा है और इसे एक समझदार, समझदार वैकल्पिक संदेश में बदल दिया है, लेकिन यह वही है जो वीडियो कहता है, और यह वही है जिसके पास बहुत अधिक अनुभव और सामान्य ज्ञान नहीं है साथ में।
रॉब ग्रांट

3
@SamuelSantana जैसा कि मैंने कहा, किसी भी समय किसी ने भी अपना हाथ रखा और कहा "एक्स के बारे में क्या?" जहाँ X एक अच्छा विचार था, उसने बस इतना ही कहा, "दूसरी कक्षा मत बनाओ।" बहुत स्पष्ट। मैं मानता हूं कि कुंजी संतुलन है; समस्या यह है कि वास्तव में :-)
रोब ग्रांट

18

मुझे लगता है कि इसे संभालने का सबसे अच्छा तरीका यह है कि अजगर खुद इसे संभालता है। अजगर एक TypeError उठाता है। उदाहरण के लिए:

$ python -c 'print(sum())'
Traceback (most recent call last):
File "<string>", line 1, in <module>
TypeError: sum expected at least 1 arguments, got 0

हमारे कनिष्ठ देव ने इस पृष्ठ को "अजगर अपवाद गलत तर्क" के लिए एक Google खोज में पाया और मुझे आश्चर्य है कि स्पष्ट (मेरे लिए) उत्तर कभी भी इस प्रश्न के पूछे जाने के दशक में सुझाया गया था।


8
मुझे कुछ भी आश्चर्य नहीं हुआ लेकिन मैं 100% सहमत हूं कि टाइपएरर सही अपवाद है यदि फ़ंक्शन में दिए गए कुछ तर्कों पर टाइप गलत है। एक ValueError उपयुक्त होगा यदि चर सही प्रकार के हों, लेकिन उनकी सामग्री और मानों का कोई मतलब नहीं है।
उपयोगकर्ता 3504575

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

2
जैसा कि @ user3504575 और @ किसी ने भी नहीं कहा, यदि फ़ंक्शन हस्ताक्षर (गलत स्थिति, गलत नाम के साथ कीवर्ड तर्क, गलत तर्क के प्रकार) के तर्क से मेल नहीं खाता है, तो TypeError का उपयोग किया जाता है, लेकिन फ़ंक्शन कॉल करने पर ValueError का उपयोग किया जाता है हस्ताक्षर से मेल खाता है लेकिन तर्क मान अमान्य हैं (उदाहरण के लिए, कॉलिंग int('a'))। स्रोत
गुडइमी

जैसा कि ओपी के प्रश्न को "अमान्य तर्क संयोजनों" के रूप में संदर्भित किया गया है, ऐसा लगता है कि एक टाइप-इयरर उचित होगा क्योंकि यह एक ऐसा मामला होगा जहां फ़ंक्शन हस्ताक्षर अनिवार्य रूप से पारित तर्कों के लिए गलत है।
जे बोन्स

आपका उदाहरण sum()बिना किसी तर्क के कॉल करता है, जो कि एक है TypeError, लेकिन ओपी तर्क के मूल्यों के "अवैध" संयोजन से चिंतित था जब तर्क प्रकार सही होते हैं। इस मामले में, दोनों saveऔर recurseबूल हैं, लेकिन अगर recurseहै Trueतो saveनहीं होना चाहिए False। यह ए ValueError। मैं सहमत हूं कि प्रश्न के शीर्षक की कुछ व्याख्या द्वारा उत्तर दिया जाएगा TypeError, लेकिन उस उदाहरण के लिए नहीं जो प्रस्तुत किया गया है।
goodmami


8

यह इस बात पर निर्भर करता है कि तर्कों के साथ समस्या क्या है।

यदि तर्क में गलत प्रकार है, तो TypeError बढ़ाएं। उदाहरण के लिए, जब आपको उन बूलियन्स में से एक के बजाय एक स्ट्रिंग मिलती है।

if not isinstance(save, bool):
    raise TypeError(f"Argument save must be of type bool, not {type(save)}")

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

यदि तर्कों में अमान्य मान हैं, तो ValueError बढ़ाएँ। यह आपके मामले में अधिक उपयुक्त लगता है:

if recurse and not save:
    raise ValueError("If recurse is True, save should be True too")

या इस विशिष्ट मामले में, पुनर्खरीद का एक सच्चा मूल्य है, बचत का एक सही मूल्य है। चूंकि मैं इसे एक त्रुटि से उबरने पर विचार करूंगा, इसलिए आप लॉग में शिकायत भी कर सकते हैं।

if recurse and not save:
    logging.warning("Bad arguments in import_to_orm() - if recurse is True, so should save be")
    save = True

मुझे लगता है कि यह सबसे सटीक उत्तर है। यह स्पष्ट रूप से कम (7 वोट मेरा सहित) है।
सियु चिंग पोंग -आसुका केंजी-

-1

मैं नहीं यकीन है कि मैं से विरासत के साथ सहमत हूँ ValueError- दस्तावेज की मेरी व्याख्या है कि है ValueErrorहै केवल builtins द्वारा उठाए गए होना चाहिए ... यह से इनहेरिट या इसे ऊपर उठाने खुद गलत लगता है।

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

- ValueError प्रलेखन


की तुलना करें google.com/codesearch?q=lang:python+class \ + \ w त्रुटि (([^ ई] \ डब्ल्यू * | ई [^ x] \ डब्ल्यू )): साथ google.com/codesearch?q=lang: अजगर + वर्ग \
_

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

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

6
Err, अगर हम इस पर बहस करने के लिए Google कोड खोजों का उपयोग करने जा रहे हैं: google.com/codesearch?q=lang%3Apython+raise%5C+ValueError # 66,300 मान बढ़ाने के मामले जिनमें Zope, xen, Django, Mozilla (और) शामिल हैं यह सिर्फ परिणामों के पहले पृष्ठ से है)। अगर एक
बिलिन

7
जैसा कि कहा गया है, दस्तावेज अस्पष्ट है। इसे या तो लिखा जाना चाहिए "जब एक अंतर्निहित ऑपरेशन या अंतर्निहित फ़ंक्शन प्राप्त होता है" या "उठाया या जब एक फ़ंक्शन या अंतर्निहित ऑपरेशन प्राप्त होता है" के रूप में। बेशक, जो भी मूल इरादे, वर्तमान अभ्यास ने इसे ट्रम्प किया है (जैसा कि @dbr बताते हैं)। इसलिए इसे दूसरे संस्करण के रूप में फिर से लिखा जाना चाहिए।
नामस्रोत

-1

अपने स्वयं के अपवाद को रोल करने के लिए मार्कस के सुझाव से सहमत हैं, लेकिन अपवाद के पाठ को स्पष्ट करना चाहिए कि समस्या तर्क सूची में है, न कि व्यक्तिगत तर्क मान। मैं प्रस्ताव करूँगा:

class BadCallError(ValueError):
    pass

उपयोग किया जाता है जब कीवर्ड तर्क गायब होते हैं जो विशिष्ट कॉल के लिए आवश्यक थे, या तर्क मान व्यक्तिगत रूप से मान्य हैं लेकिन एक दूसरे के साथ असंगत हैं। ValueErrorतब भी सही होगा जब एक विशिष्ट तर्क सही प्रकार लेकिन सीमा से बाहर हो।

क्या यह पायथन में एक मानक अपवाद नहीं होना चाहिए?

सामान्य तौर पर, मैं फ़ंक्शन (मेरी गलती) के बुरे परिणामों से किसी फ़ंक्शन (कॉलर की गलती) के लिए खराब इनपुट को अलग करने में पायथन शैली को थोड़ा तेज होना चाहूंगा। इसलिए स्थानीय लोगों में मूल्य त्रुटियों से तर्कों में मूल्य त्रुटियों को अलग करने के लिए एक BadArgumentError भी हो सकता है।


मैं KeyErrorनहीं मिला कीवर्ड के लिए बढ़ाता हूँ (क्योंकि एक स्पष्ट सुस्पष्ट खोजशब्द शब्दार्थ के समान है जो **kwargsउस कुंजी को याद नहीं कर रहा है)।
काउबर्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.