Gebruik van 'argparse.ArgumentError' in Python

Ik wil de uitzondering ArgumentError gebruiken in de module argparse in Python, maar ik kan niet achterhalen hoe ik deze moet gebruiken. De handtekening zegt dat het moet worden genoemd als ArgumentError (argument, bericht) , maar ik kan niet achterhalen wat argument zou moeten zijn. Ik denk dat het een deel van het parser-object zou moeten zijn, maar ik kon er geen documentatie voor vinden.

35
U kunt het gebruiken in een aangepaste Action -klasse, net als de bestaande klassen. Maar ik kan me geen reden voorstellen om dit te doen buiten de parser . Het doet niets bijzonders - voegt gewoon de naam Action toe aan het foutbericht. Bestudeer het gebruik ervan in de code.
toegevoegd de auteur hpaulj, de bron
toegevoegd de auteur DavidRR, de bron

2 antwoord

Van de brondocumentatie :

ArgumentError: de uitzondering gegenereerd door ArgumentParser-objecten wanneer er fouten zijn met de acties van de parser. Fouten die tijdens het ontleden van de opdrachtregel worden opgehaald, worden door ArgumentParser opgevangen en als opdrachtregelberichten verzonden.

De parameter argument van de constructor is het object Actie waaruit de uitzondering afkomstig is. Meestal is het niet nodig om het op te tillen buiten een Action -subklasse, en bij het subclasseren ervan is het niet nodig het expliciet te verhogen; meestal raise je ValueError (of wat toepasselijk is).

Zwevende waarden tussen 0 en 1

Met betrekking tot uw opmerking, dat u alleen drijvende-kommawaarden tussen 0 en 1 wilt accepteren. Gebruik hiervoor de mogelijkheid om aangepaste typen te definiëren. Je kunt het bijvoorbeeld op deze manier doen:

def percentFloat (string):
    value = float(string)
    if value < 0 or value > 1:
        raise argparse.ArgumentTypeError('Value has to be between 0 and 1')
    return value

parser = argparse.ArgumentParser()
parser.add_argument('test', type=percentFloat)
parser.parse_args()

Merk op dat dit ook veilig is voor niet-drijvers omdat zweven (tekenreeks) een ValueError zal genereren voor niet-drijvers die ook een ongeldige typefout veroorzaakt door de argaret module. ArgumentTypeError is slechts een manier om op te geven een aangepast foutbericht.

Wederzijdse exclusieve parameters

For Wederzijdse exclusieve parameters, you should use argparse.add_mutually_exclusive_group.

Parameterafhankelijkheid

Parameterafhankelijkheid isn’t really something that should be done by the argument parser. For semantic details, you should instead simply do it yourself:

args = parser.parse_args()
if args.w and not args.p:
    parser.error('-p is required when -w is set.')

U kunt ArgumentParser.error gebruiken om aangepaste foutmelding die het programma zal onderbreken en afdrukken naar de console.

Maar natuurlijk zou het in een dergelijke basissituatie veel logischer zijn om zo mogelijk impliciet -p te raden.

49
toegevoegd
Dat klopt niet. Als ik gewoon de waarde verzend, krijg ik AttributeError: 'float'-object heeft geen kenmerk' option_strings '.
toegevoegd de auteur asmeurer, de bron
En trouwens, ik wil het gebruiken omdat ik het type wil controleren dat de module niet direct ondersteunt. Ik wil bijvoorbeeld een drijvende-kommawaarde tussen 0 en 1. Met argparse kunt u opgeven dat het een zwevend niveau moet zijn, maar ik moet het bereik handmatig controleren. Dit lijkt de juiste fout te zijn wanneer de waarde verkeerd is.
toegevoegd de auteur asmeurer, de bron
De downvote is omdat het antwoord fout is. ArgumentError (1.1, "Waarde buiten bereik") verhoogt AttributeError, zoals ik hierboven al vermeldde. Dit moet een soort van objectief object zijn, maar ik weet niet wat. En trouwens, een ander voorbeeld van wanneer je dit zou willen doen, is wanneer je een niet-triviale afhankelijkheid van de argumenten wilt definiëren, die, voor zover ik kan zien, de argparse module niet direct ondersteunt. Iets als de -w optie vereist dat de -p optie, of -n en -N wederzijds exclusief zijn.
toegevoegd de auteur asmeurer, de bron
Bedankt. Die parser.error was wat ik zocht.
toegevoegd de auteur asmeurer, de bron
@asmeurer Bewerkt mijn antwoord om u een voorbeeld te geven over hoe u dat moet doen.
toegevoegd de auteur poke, de bron
Mijn antwoord bijgewerkt.
toegevoegd de auteur poke, de bron

Hoewel parser.error() is wat de meeste mensen waarschijnlijk willen, is het ook mogelijk om argparse.ArgumentError() (zoals de vraag stelt) te gebruiken. U hebt een verwijzing naar het argument nodig, zoals de bar_arg in het onderstaande voorbeeld:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--foo')
bar_arg = parser.add_argument('--bar')

args = parser.parse_args()
if args.bar == 'xyzzy':
    raise argparse.ArgumentError(bar_arg, "Can't be 'xyzzy'")

if args.foo == 'xyzzy':
    parser.error("Can't be 'xyzzy'")

Dit resulteert in uitvoer zoals hieronder:

$ python argparse_test.py --foo xyzzy
usage: argparse_test.py [-h] [--foo FOO] [--bar BAR]
argparse_test.py: error: Can't be 'xyzzy'

$ python argparse_test.py --bar xyzzy
Traceback (most recent call last):
  File "argparse_test.py", line 10, in 
    raise argparse.ArgumentError(bar_arg, "Can't be 'xyzzy'")
argparse.ArgumentError: argument --bar: Can't be 'xyzzy'
11
toegevoegd
Dit is een goed voorbeeld van hoe het gebruik van ArgumentError buiten de parser mogelijk is, maar waarschijnlijk minder dan parser.error .
toegevoegd de auteur hpaulj, de bron
Nou, als je je foutmelding goed schrijft, dan zou je vermelden welke schakelaar de beledigende was. Het creëren van een afzonderlijke variabele voor elk toegevoegd argument kan erg omslachtig zijn ...
toegevoegd de auteur Praveen, de bron
@hpaulj, ja, maar ArgumentError heeft één voordeel: het laat je weten welke schakelaar de aanstootgevende was.
toegevoegd de auteur ukrutt, de bron
@Praveen Het is een kwestie van voorkeur, denk ik. Ik geef er de voorkeur aan dat de variabele voor schrijven "'--foo' niet 'xyzzy'" kan zijn, omdat ik dan moet onthouden wat de juiste naam van de schakelaar was (het is niet noodzakelijk hetzelfde als het kenmerk voor args ). Maar eerlijk gezegd denk ik dat parser.error() standaard de naam van de overtredende switch moet bevatten.
toegevoegd de auteur ukrutt, de bron