파이썬에서 나쁜 / 잘못된 인수 조합에 대해 어떤 예외를 제기해야합니까?


543

파이썬에서 잘못된 인수 조합을 나타내는 모범 사례가 궁금합니다. 나는 당신이 다음과 같은 기능을하는 몇 가지 상황을 겪었습니다.

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있습니다. 모든 사람들이 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.
ere on

2
가변 개수의 인수가있는 함수 (예 : 인수가 짝수의 인수 여야하는 함수)에 대해 인수가 NUMBER 개의 인수에있는 경우 일관성을 유지하려면 TypeError를 발생시켜야합니다. a) 사용 사례가 있거나 b) 다른 사람이 사용하기 위해 라이브러리를 내 보내지 않는 한 자신 만의 클래스를 만들지 마십시오. 조기 기능은 코드의 죽음입니다.
Erik Aronesty

104

나는 ~로부터 물려 받았다 ValueError

class IllegalArgumentError(ValueError):
    pass

때로는 자신 만의 예외를 만드는 것이 좋지만 가능한 한 원하는 것과 가까운 내장 예외를 상속하는 것이 좋습니다.

특정 오류를 잡아야하는 경우 이름을 갖는 것이 도움이됩니다.


26
수업 및 맞춤 예외 작성 중지 -pyvideo.org/video/880/stop-writing-classes
Hamish Grubijan

40
@HamishGrubijan 그 비디오는 끔찍합니다. 누군가가 수업을 잘 활용할 것을 제안했을 때, 그는 단지 "수업을 사용하지 마십시오." 훌륭한. 수업은 좋습니다. 그러나 내 말을 받아들이지 마십시오 .
Rob Grant

12
@RobertGrant 아니오, 당신은 그것을 얻지 못합니다. 그 비디오는 문자 그대로 "클래스를 사용하지 마십시오"에 관한 것이 아닙니다. 지나치게 복잡하지는 않습니다.
RayLuo

15
@RayLuo 당신은 비디오의 말을 온전하게 점검하고 그것을 맛있고 합리적인 대체 메시지로 변환했을 수도 있지만, 그것은 비디오가 말하는 것입니다. 많은 경험과 상식이없는 사람이 사라질 것입니다 와.
Rob Grant

3
내가 말했듯이 @SamuelSantana, 누군가가 손을 들고 "X는 어떻습니까?" X는 좋은 아이디어 였지만 방금 "다른 수업을 만들지 말라"고 말했다. 꽤 분명합니다. 열쇠가 균형이라는 데 동의합니다. 문제는 그것이 실제로 막보기에는 너무 모호하다는 것입니다. :-)
Rob Grant

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

우리 주니어 개발자는 구글 검색에서 "파이썬 예외 잘못된 논증"에 대한이 페이지를 발견했으며이 질문이 제기 된 이후 10 년 동안 명백한 (나에게) 대답이 제안되지 않은 것에 놀랐습니다.


8
놀랍지는 않지만 TypeError가 함수에 전달 된 일부 인수에서 잘못된 경우 TypeError가 올바른 예외라는 100 %에 동의합니다. 변수가 올바른 유형이지만 내용과 값이 의미가없는 경우 ValueError가 적합합니다.
user3504575

나는 이것이 아마도 인수에 대해 누락되거나 호출되지 않았을 것이라고 생각하지만, 문제는 올바르게 주어진 인수에 관한 것이지만 주어진 인수 의 가치 를 포함하는 더 높은 추상화 수준에서는 부정확합니다 . 그러나 나는 실제로 전자를 찾고 있었으므로 어쨌든 찬성 투표를하십시오.
아무도

2
@ user3504575와 @Nobody가 말했듯이, 인수가 함수 시그니처 (잘못된 위치 인수, 이름이 잘못된 키워드 인수, 잘못된 인수 유형)와 일치하지 않으면 TypeError가 사용되지만 함수 호출시 ValueError가 사용됩니다. 서명과 일치하지만 인수 값이 유효하지 않습니다 (예 :을 호출 int('a')). 출처
goodmami

OP의 질문은 "유효하지 않은 인수 조합"에 대한 것으로서, 전달 된 인수에 대해 함수 서명이 본질적으로 잘못된 경우 TypeError가 적절할 것 같습니다.
J Bones

예제 sum()에서는 인수가없는 인수 를 호출 TypeError하지만 인수 유형이 올바른 경우 OP는 인수 값의 "잘못된"조합과 관련이있었습니다. 이 경우, 모두 saverecursebools하지만 경우 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)}")

그러나 파이썬에서는 이와 같은 검사를 거의하지 않습니다. 만약 그 주장이 실제로 유효하지 않다면, 더 깊은 기능이 아마도 우리에게 불평을 할 것입니다. 부울 값만 확인하면 나중에 일부 코드 사용자는 비어 있지 않은 문자열이 항상 True라는 것을 알고 문자열을 제공 할 것입니다. 캐스트를 구할 수도 있습니다.

인수에 유효하지 않은 값이 있으면 ValueError를 발생시킵니다. 이것은 귀하의 경우에 더 적절 해 보입니다.

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

또는이 특정한 경우, 재귀의 True 값을 갖는 것은 True 값의 저장을 의미합니다. 이 오류를 복구 한 것으로 간주하므로 로그에 불만을 표시 할 수도 있습니다.

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

이것이 가장 정확한 답변이라고 생각합니다. 이것은 분명히 과소 평가되었다 (현재까지 7 표).
Siu Ching Pong -Asuka Kenji-

-1

나는 확실히 내가로부터 상속에 동의하지있어 ValueError그가되는 설명서의 내 해석 - ValueError입니다 그것으로부터 상속 또는 자신이 잘못된 것 같다 그것을 제기 ... 내장 명령에 의해 제기 할 예정.

내장 연산 또는 함수가 올바른 유형이지만 부적절한 값을 갖는 인수를 수신하고 상황이 IndexError와 같은보다 정확한 예외에 의해 설명되지 않을 때 발생합니다.

- ValueError를 문서


비교 google.com/codesearch?q=lang:python+class \ + \ w 오류 (\ [E ^] (w * | [^ X] \ w E ))와 google.com/codesearch?q=lang : python + class \ + \ w * Error (예외) :
Markus Jarderot

13
이 블러는 단순히 빌트인이 올릴 수있는 것이 아니라 빌트인 만이 올릴 수 있다는 것을 의미 합니다. 이 경우 파이썬 문서가 외부 라이브러리가 제기하는 것에 대해 이야기하는 것이 전적으로 적합하지는 않습니다.
Ignacio Vazquez-Abrams

5
내가 본 모든 Python 소프트웨어 ValueError는 이런 종류의 것들에 사용되었으므로 문서를 너무 많이 읽으려고한다고 생각합니다.
James Bennett

6
Err, Google 코드 검색을 사용하여이를 주장 할 경우 : google.com/codesearch?q=lang%3Apython+raise%5C+ValueError # Zope, xen, Django, Mozilla를 포함한 ValueError를 발생시키는 66,300 건 그것은 결과의 첫 페이지에서 나온 것입니다). 내장 예외가 맞는 경우이를 사용하십시오.
dbr

7
명시된 바와 같이, 문서는 모호하다. "내장 조작 또는 내장 기능 수신시 발생"또는 "기능 또는 내장 조작 수신시 발생"으로 작성되어야합니다. 물론, 원래 의도가 무엇이든, 현재 관행은 @dbr이 지적한 것처럼 그것을 능가했습니다. 따라서 두 번째 변형으로 다시 작성해야합니다.
시조

-1

Markus의 제안에 동의하여 자신의 예외를 굴리십시오. 그러나 예외 텍스트는 문제가 개별 인수 값이 아니라 인수 목록에 있음을 명확히해야합니다. 나는 제안 할 것이다 :

class BadCallError(ValueError):
    pass

특정 호출에 필요한 키워드 인수가 누락되었거나 인수 값이 개별적으로 유효하지만 서로 일치하지 않을 때 사용됩니다. ValueError특정 인수가 올바른 유형이지만 범위를 벗어난 경우에도 여전히 옳습니다.

이것이 파이썬에서 표준 예외가 아니어야합니까?

일반적으로 파이썬 스타일은 함수의 잘못된 입력 (발신자의 결함)과 함수의 나쁜 결과 (내 결함)를 구별하는 데 조금 더 선명하고 싶습니다. 따라서 인수의 값 오류를 로컬의 값 오류와 구별하기 위해 BadArgumentError도있을 수 있습니다.


나는 인상 것 KeyError(누락 된 명시 적 키워드가 의미 적으로 동일하기 때문에 발견되지 키워드를 **kwargs해당 키가 누락 DICT).
cowbert
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.