web-dev-qa-db-fra.com

Argparse: Les arguments requis sont énumérés sous "arguments optionnels"?

J'utilise le code simple suivant pour analyser certains arguments; notez que l'un d'eux est requis. Malheureusement, lorsque l'utilisateur exécute le script sans fournir d'argument, le texte d'utilisation/d'aide affiché n'indique pas qu'il existe un argument non facultatif, ce qui me semble très déroutant. Comment obtenir python pour indiquer qu'un argument n'est pas facultatif?

Voici le code:

import argparse
if __== '__main__':
    parser = argparse.ArgumentParser(
        description='Foo')
    parser.add_argument('-i','--input', help='Input file name', required=True)
    parser.add_argument('-o','--output', help='Output file name', default="stdout")
    args = parser.parse_args()
    print ("Input file: %s" % args.input )
    print ("Output file: %s" % args.output )

Lorsque j'exécute le code ci-dessus sans fournir l'argument requis, j'obtiens le résultat suivant:

usage: foo.py [-h] -i INPUT [-o OUTPUT]

Foo

optional arguments:
    -h, --help            show this help message and exit
    -i INPUT, --input INPUT
                          Input file name
    -o OUTPUT, --output OUTPUT
                          Output file name
174
mort

Les paramètres commençant par - ou -- sont généralement considérés comme facultatifs. Tous les autres paramètres sont des paramètres de position et, en tant que tels, requis par la conception (comme les arguments de fonction de position). Il est possible d'exiger des arguments optionnels, mais c'est un peu contre leur conception. Comme ils font toujours partie des arguments non positionnels, ils seront toujours listés sous l'en-tête source de confusion "arguments optionnels" même s'ils sont requis. Les crochets manquants dans la partie utilisation montrent toutefois qu'ils sont effectivement nécessaires.

Voir aussi le documentation :

En général, le module argparse suppose que des indicateurs tels que -f et --bar indiquent des arguments facultatifs, qui peuvent toujours être omis sur la ligne de commande.

Remarque: Les options obligatoires sont généralement considérées comme des formes inappropriées, car les utilisateurs s'attendent à ce qu'elles soient facultatives. Par conséquent, elles doivent être évitées dans la mesure du possible.

Cela dit, les en-têtes "arguments de position" et "arguments facultatifs" de l'aide sont générés par deux groupes d'arguments dans lesquels les arguments sont automatiquement séparés en. Maintenant, vous pouvez "pirater" et changer le nom des options, mais une solution beaucoup plus élégante consisterait à créer un autre groupe pour les "arguments nommés obligatoires" (ou ce que vous voulez appeler).

parser = argparse.ArgumentParser(description='Foo')
parser.add_argument('-o', '--output', help='Output file name', default='stdout')
requiredNamed = parser.add_argument_group('required named arguments')
requiredNamed.add_argument('-i', '--input', help='Input file name', required=True)
parser.parse_args(['-h'])
usage: [-h] [-o OUTPUT] -i INPUT

Foo

optional arguments:
  -h, --help            show this help message and exit
  -o OUTPUT, --output OUTPUT
                        Output file name

required named arguments:
  -i INPUT, --input INPUT
                        Input file name
254
poke

Etant donné que je préfère lister les arguments requis avant d’être facultatifs, je le pirate via:

    parser = argparse.ArgumentParser()
    parser._action_groups.pop()
    required = parser.add_argument_group('required arguments')
    optional = parser.add_argument_group('optional arguments')
    required.add_argument('--required_arg', required=True)
    optional.add_argument('--optional_arg')
    return parser.parse_args()

et cela génère:

usage: main.py [-h] [--required_arg REQUIRED_ARG]
               [--optional_arg OPTIONAL_ARG]

required arguments:
  --required_arg REQUIRED_ARG

optional arguments:
  --optional_arg OPTIONAL_ARG

Je peux vivre sans 'aide' dans le groupe d'arguments facultatifs.

54
Karl Rosaen

Bâtiment de Karl Rosaen

parser = argparse.ArgumentParser()
optional = parser._action_groups.pop() # Edited this line
required = parser.add_argument_group('required arguments')
# remove this line: optional = parser...
required.add_argument('--required_arg', required=True)
optional.add_argument('--optional_arg')
parser._action_groups.append(optional) # added this line
return parser.parse_args()

et cela génère:

usage: main.py [-h] [--required_arg REQUIRED_ARG]
           [--optional_arg OPTIONAL_ARG]

required arguments:
  --required_arg REQUIRED_ARG

optional arguments:
  -h, --help                    show this help message and exit
  --optional_arg OPTIONAL_ARG
33
RalphyZ

Une fois de plus, en s'appuyant sur @RalphyZ

Celui-ci ne casse pas l'API exposée.

from argparse import ArgumentParser, SUPPRESS
# Disable default help
parser = ArgumentParser(add_help=False)
required = parser.add_argument_group('required arguments')
optional = parser.add_argument_group('optional arguments')

# Add back help 
optional.add_argument(
    '-h',
    '--help',
    action='help',
    default=SUPPRESS,
    help='show this help message and exit'
)
required.add_argument('--required_arg', required=True)
optional.add_argument('--optional_arg')

Ce qui affichera la même chose que ci-dessus et devrait survivre aux versions futures:

usage: main.py [-h] [--required_arg REQUIRED_ARG]
           [--optional_arg OPTIONAL_ARG]

required arguments:
  --required_arg REQUIRED_ARG

optional arguments:
  -h, --help                    show this help message and exit
  --optional_arg OPTIONAL_ARG
1
Bryan_D