2016-08-27 11 views
3

Ich möchte, dass das Programm sich gegenseitig ausschließende Positionsargumente akzeptiert, und die Verwendung als eine Gruppe von Argumenten angezeigt werden.
Zur Zeit konnte ich nur einen erreichen oder das andere, aber nicht beides ...Python: sich gegenseitig ausschließende Positionsargumente

Dies ist, was ich derzeit haben:

def parse_arguments(): 
    arg_parser = argparse.ArgumentParser(description = 'Project Builder') 

    query_parser = arg_parser.add_argument_group('query', "Query current state") 
    build_parser = arg_parser.add_argument_group('build', "Build project") 

    # query arguments 
    query_parser.add_argument('-s', '--servers', 
       action = 'store_true', 
       required = False, 
       help  = 'Display available servers') 

    query_parser.add_argument('-u', '--users', 
       action = 'store_true', 
       required = False, 
       help  = 'Display current users') 



    # build arguments 
    build_parser.add_argument('-f', '--force', 
       action = 'store', 
       required = False, 
       metavar = 'SERVER_NAME', 
       help  = 'Force build on SERVER_NAME') 

    build_parser.add_argument('-c', '--clean', 
       action = 'store_true', 
       required = False, 
       help  = 'Clean repo before build') 

    build_parser.add_argument('-v', '--verbosity', 
       action = 'store_true', 
       required = False, 
       help  = 'Print stderr to console') 

    build_parser.add_argument('-p', '--project', 
       action = 'store', 
       required = True, 
       metavar = 'project_A|project_B|project_C', 
       type  = project_name, 
       help  = 'Project to build (required)') 

    return vars(arg_parser.parse_args()) 


args = parse_arguments() 

Welche ergibt folgendes:

usage: test.py [-h] [-s] [-u] [-f SERVER_NAME] [-c] [-v] -p 
       project_A|project_B|project_C 

Project Builder 

optional arguments: 
    -h, --help   show this help message and exit 

query: 
    Query current state 

    -s, --servers   Display available servers 
    -u, --users   Display current users 

build: 
    Build project 

    -f SERVER_NAME, --force SERVER_NAME 
         Force build on SERVER_NAME 
    -c, --clean   Clean repo before build 
    -v, --verbosity  Print stderr to console 
    -p project_A|project_B|project_C, --project project_A|project_B|project_C 
         Project to build (required) 

Aber was Ich möchte wirklich, dass query und build zwei einander ausschließende Positionsargumente sind.

Ich versuchte subparsers wie folgt verwendet:

def parse_arguments(): 
    arg_parser = argparse.ArgumentParser(description = 'Project Builder') 
    command_parser = arg_parser.add_subparsers(help = "Command") 

    query_parser = command_parser.add_parser('query', help = "Query current state") 
    build_parser = command_parser.add_parser('build', help = "Build project") 

    # query arguments 
    query_parser.add_argument('-s', '--servers', 
       action = 'store_true', 
       required = False, 
       help  = 'Display available servers') 

    query_parser.add_argument('-u', '--users', 
       action = 'store_true', 
       required = False, 
       help  = 'Display current users') 



    # build arguments 
    build_parser.add_argument('-f', '--force', 
       action = 'store', 
       required = False, 
       metavar = 'SERVER_NAME', 
       help  = 'Force build on SERVER_NAME') 

    build_parser.add_argument('-c', '--clean', 
       action = 'store_true', 
       required = False, 
       help  = 'Clean repo before build') 

    build_parser.add_argument('-v', '--verbosity', 
       action = 'store_true', 
       required = False, 
       help  = 'Print stderr to console') 

    build_parser.add_argument('-p', '--project', 
       action = 'store', 
       required = True, 
       metavar = 'project_A|project_B|project_C', 
       type  = project_name, 
       help  = 'Project to build (required)') 

    return vars(arg_parser.parse_args()) 

Aber das erzeugt folgendes:

usage: test.py [-h] {query,build} ... 

Project Builder 

positional arguments: 
    {query,build} Command 
    query  Query current state 
    build  Build project 

optional arguments: 
    -h, --help  show this help message and exit 

Wo, was ich will eine Kombination der beiden Versuche oben ist, nämlich:

usage: test.py [-h] {query,build} ... 

Project Builder 

optional arguments: 
    -h, --help   show this help message and exit 

query: 
    Query current state 

    -s, --servers   Display available servers 
    -u, --users   Display current users 

build: 
    Build project 

    -f SERVER_NAME, --force SERVER_NAME 
         Force build on SERVER_NAME 
    -c, --clean   Clean repo before build 
    -v, --verbosity  Print stderr to console 
    -p project_A|project_B|project_C, --project project_A|project_B|project_C 
         Project to build (required) 

Wo sich query und build gegenseitig ausschließen.
Ich weiß über die ArgumentParser.add_mutually_exclusive_group(required=False) Methode, aber mit es half nicht zu erreichen, was ich wollte, da 1) die Argumente müssen optional sein, wenn Sie es verwenden, und 2) das usage Format ist nicht wie ich will.

Antwort

0

Im ersten Szenario könnten Sie -p Entscheidungen

build_parser.add_argument('-p', '--project', 
      action = 'store', # default 
      required = True, 
      choices = ['project_A','project_B','project_C'], 
      # type  = project_name, # doesn't make sense 
      help  = 'Project to build (required)') 

oder als Positions

build_parser.add_argument('project', 
      choices = ['project_A','project_B','project_C'], 
      help  = 'Project to build') 

type geben muss eine Funktion sein, eine, die etwas als String konvertiert Sie wollen, zB int('1') , float('12.343').

Die Verwendung von Subparsern ist ähnlich. Für den Hauptparser ist das Subparser-Argument nur eine Position mit Auswahlmöglichkeiten. Die durchgeführte Aktion besteht jedoch darin, das Parsen der übrigen Argumente für den Subparser zu delegieren.

Zwei sich gegenseitig ausschließende positionals nicht logischen Sinn machen

`[foo | bar]` 

Es kann nicht sagen, basierend nur auf Position, ob Sie die Zeichenfolge foo oder bar zuweisen möchten. Sie sind jedoch daran interessiert, Werte auf der Grundlage von Werten zuzuweisen, oder eher Werte auf eine Reihe von Auswahlmöglichkeiten zu beschränken.

Ohne sorgfältig darauf zu achten, sieht Ihr Subparser-Code richtig aus und sollte die Eingabe wie gewünscht analysieren. Hast du es getestet?

Das Hilfedisplay für Subparser ist nicht so flexibel wie es sein könnte, aber das Nacharbeiten kostet ziemlich viel Arbeit (es gibt SO Fragen dazu). Das aktuelle Setup sieht separate Hilfeanzeigen für den Hauptparser und für jeden der Unterparser vor. Es gibt keine integrierte umfassende Hilfeanzeige.

+0

'type = project_name' macht Sinn, da' project_name' ein Funktionsname ist (Verifier, der prüft, ob der Projektname korrekt ist). Ich denke, "zwei einander ausschließende Positionsargument" ist nicht die beste Wahl der Wörter ... Was ich will ist ein 'git'-ähnliches Verhalten, wo der Benutzer Unterbefehl bereitstellen muss (das" sich gegenseitig ausschließende Positionargument "wäre' log', 'status',' show', 'branch', etc ...). –

+0

Wenn 'project_name' Ihre eigene Funktion ist, dann wird wahrscheinlich der 'Auswahl'-Test durchgeführt. Ich bin es gewohnt, dass Poster diesen Parameter mißbrauchen, weil sie denken, dass sie eine Objektklasse spezifiziert. Ich denke, die "Subparser" sollen sich als Unterbefehle in anderen Systemen verhalten, obwohl ich mir sicher bin, dass sie sich in Details unterscheiden. – hpaulj

Verwandte Themen