簡體   English   中英

對於 Python 中的錯誤/非法參數組合,我應該引發哪個異常?

[英]Which exception should I raise on bad/illegal argument combinations in Python?

我想知道在 Python 中指示無效參數組合的最佳實踐。 我遇到過一些情況,你有這樣的功能:

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 中存在java.lang.IllegalArgumentException - 是否很好理解每個人都會在 Python 中創建自己的BadValueError或者是否有另一種首選方法?

我只會提高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相同,那么為什么不使用它呢?

我會從ValueError繼承

class IllegalArgumentError(ValueError):
    pass

有時最好創建自己的異常,但從內置異常繼承,這盡可能接近您想要的。

如果您需要捕獲該特定錯誤,擁有一個名稱會很有幫助。

我認為處理這個問題的最好方法是 python 本身處理它的方式。 Python 引發了一個 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

我們的初級開發人員剛剛在谷歌搜索“python 異常錯誤參數”中找到了這個頁面,我很驚訝自問這個問題以來的十年里,沒有人提出明顯的(對我來說)答案。

這取決於參數的問題是什么。

如果參數的類型錯誤,則引發 TypeError。 例如,當您獲得一個字符串而不是那些布爾值之一時。

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

但是請注意,在 Python 中我們很少進行這樣的檢查。 如果參數確實無效,一些更深層次的函數可能會為我們抱怨。 如果我們只檢查布爾值,也許某些代碼用戶稍后會向它提供一個字符串,因為知道非空字符串始終為 True。 這可能會為他節省一個演員。

如果參數具有無效值,則引發 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

我主要只是看到在這種情況下使用的內置ValueError

在這種情況下,您很可能會使用ValueErrorraise ValueError() in full),但這取決於錯誤值的類型。 例如,如果您創建了一個只允許字符串的函數,而用戶輸入的是一個整數,那么您將使用TypeError 如果用戶輸入了錯誤的輸入(意味着它具有正確的類型但不符合某些條件),則Value Error將是您的最佳選擇。 Value Error 也可用於阻止程序發生其他異常,例如,您可以使用ValueError來阻止 shell 表單引發ZeroDivisionError ,例如,在此函數中:

def function(number):
    if not type(number) == int and not type(number) == float:
        raise TypeError("number must be an integer or float")
    if number == 5:
        raise ValueError("number must not be 5")
    else:
        return 10/(5-number)

PS 有關 python 內置異常的列表,請轉到此處: https : //docs.python.org/3/library/exceptions.html (這是官方 python 數據庫)

我不確定我是否同意從ValueError繼承——我對文檔的解釋是ValueError應該由內置函數引發……從它繼承或自己引發似乎不正確。

當內置操作或函數接收到類型正確但值不合適的參數時引發,並且這種情況沒有用更精確的異常(如 IndexError)描述。

-- ValueError 文檔

同意 Markus 的建議,推出您自己的例外,但例外的文本應闡明問題出在參數列表中,而不是單個參數值中。 我建議:

class BadCallError(ValueError):
    pass

當缺少特定調用所需的關鍵字參數,或參數值單獨有效但彼此不一致時使用。 當特定參數是正確類型但超出范圍時, ValueError仍然是正確的。

這不應該是 Python 中的標准異常嗎?

一般來說,我希望 Python 風格在區分函數的錯誤輸入(調用者的錯誤)和函數中的錯誤結果(我的錯誤)方面更加清晰。 所以也可能有一個 BadArgumentError 來區分參數中的值錯誤和局部變量中的值錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM