Hvilke unntak skal jeg reise på dårlige / ulovlig argument kombinasjoner i Python?

stemmer
369

Jeg lurte på om de beste praksis for å indikere ugyldig argument kombinasjoner i Python. Jeg har kommet over noen situasjoner der du har en funksjon slik:

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

Den eneste ergrelse med dette er at hver pakke har sin egen, vanligvis litt forskjellig BadValueError. Jeg vet at i Java det eksisterer java.lang.IllegalArgumentException- det er godt forstått at alle vil være å skape sine egne BadValueErrors i Python eller er det en annen, foretrukket metode?

Publisert på 01/11/2008 klokken 23:02
kilden bruker
På andre språk...                            


7 svar

stemmer
8

Jeg har stort sett bare sett den innebygde ValueErrorbrukes i denne situasjonen.

Svarte 01/11/2008 kl. 23:17
kilden bruker

stemmer
78

Jeg vil arve fra ValueError

class IllegalArgumentError(ValueError):
    pass

Noen ganger er det bedre å lage dine egne unntak, men arve fra en innebygd en, som er så nær det du ønsker som mulig.

Hvis du trenger å ta den spesifikke feilen, er det nyttig å ha et navn.

Svarte 01/11/2008 kl. 23:17
kilden bruker

stemmer
2

Jeg vet ikke om jeg er enig med arven fra ValueError- min tolkning av dokumentasjon som ValueErrorer kun ment å bli oppdratt av builtins ... arve fra den eller heve det selv virker feil.

Hevet når en innebygd i drift eller funksjon mottar et argument som har den riktige type, men en upassende verdi, og situasjonen er ikke beskrevet ved en mer nøyaktig unntak slik som IndexError.

- ValueError dokumentasjon

Svarte 01/11/2008 kl. 23:21
kilden bruker

stemmer
410

Jeg ville bare heve ValueError , med mindre du trenger en mer spesifikk unntak ..

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

Det er egentlig ikke noe poeng i å gjøre class BadValueError(ValueError):pass- den egendefinerte klasse er identisk i bruk for å ValueError , så hvorfor ikke bruke det?

Svarte 01/11/2008 kl. 23:37
kilden bruker

stemmer
0

Enig med Markus' forslag om å rulle din egen unntak, men teksten unntaket bør klargjøre at problemet er i argumentlisten, ikke de enkelte argumentverdier. Jeg vil foreslå:

class BadCallError(ValueError):
    pass

Brukes når søkeord argumenter mangler som var nødvendig for ønsket samtale, eller argumentverdier er individuelt gyldig, men i strid med hverandre. ValueErrorvil fortsatt være rett når et bestemt argument er riktig type, men utenfor rekkevidde.

Burde ikke dette være en standard unntak i Python?

Generelt vil jeg gjerne Python-stil å være litt skarpere skille dårlige innganger til en funksjon (feil som ringer) fra dårlige resultater innen funksjonen (min feil). Så det er kanskje også en BadArgumentError å skille verdi feil i argumentene fra verdi feil i lokalbefolkningen.

Svarte 05/10/2017 kl. 15:20
kilden bruker

stemmer
2

Jeg tror den beste måten å håndtere dette er måten python selv håndterer det. Python reiser en Typeerror. For eksempel:

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

Våre junior dev bare fant denne siden i et google søk etter "python unntaks feil argumenter", og jeg er overrasket over at det åpenbare (for meg) ikke svaret noen gang ble foreslått i tiåret siden dette spørsmålet ble stilt.

Svarte 01/08/2018 kl. 16:17
kilden bruker

stemmer
0

Det kommer an på hva problemet med argumentene er.

Hvis argumentet er feil type, heve et Typeerror. For eksempel, når du får en streng i stedet for en av disse Booleans.

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

Vær imidlertid oppmerksom på at det i Python vi sjelden gjør noen kontroller som dette. Hvis argumentet egentlig er ugyldig, vil noen dypere funksjon sannsynligvis gjøre den klagende for oss. Og hvis vi bare sjekke boolsk verdi, kanskje noen kode brukeren vil senere bare mate den en streng vel vitende om at ikke-tomme strenger er alltid sann. Det kan redde ham en støpt.

Hvis argumentene har ugyldige verdier, heve ValueError. Dette synes mer hensiktsmessig i ditt tilfelle:

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

Eller i dette konkrete tilfellet, har en sann verdi av recurse innebære en sanne verdien av lagre. Siden jeg ville vurdere dette en utvinning fra en feil, kan du også ønsker å klage i loggen.

if recurse and not save:
    logging.warning("Bad arguments in import_to_orm() - if recurse is True, so should save be")
    save = True
Svarte 25/06/2019 kl. 11:47
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more