2017-01-25 2 views
2

Ich schreibe ein Python-Skript, es benötigt entweder 3 Positionsargumente (Name, Datum, Ort, sagen wir mal) oder 1 Argument, das eine Setup-Datei ist, die diese Information enthält.Python-Skript mit 1 oder 3 Positionsargumenten

Ich weiß, dass ich kann argparse verwenden und ich kann die Positionsargumente optional mit machen:

parser.add_argument('name_OR_setupFile') 
parser.add_argument('date', nargs='?') 
parser.add_argument('location', nargs='?') 

und dann kann ich Fehler-Check, um sicherzustellen, dass der Benutzer nicht nichts getan dumm

Das Problem ist, dass jetzt die Hilfe-Nachricht sehr verwirrend sein wird, weil es unklar ist, was das erste Argument wirklich ist. Ich würde gerne einen Weg, dies als zwei verschiedene add_argument Linien, irgendwie, aber ich bin mir nicht sicher, wie.

Ich weiß auch, dass ich ein --setupFile Argument verwenden könnte, und machen Sie die drei optional ... aber ich würde es lieber nicht tun, wenn ich nicht muss.

Eine dritte Möglichkeit ist die Verwendung:

parser.add_argument('ARGS', nargs='+', help='ARGS is either of the form setupFile, or name date location') 

und dann später Fehlerprüfung ...

ETA zur Klarstellung:

Ich möchte das Skript aufrufen können, entweder mit:

python foo.py setupFile 

oder

python foo.py name date location 

Ich möchte den Text Hilfe so etwas wie sein:

usage: 
foo.py setupFile 
foo.py name date location 
+0

Können Sie bitte auf mehr klar sein, was Sie brauchen? Sie können die Hilfemeldung im Aufruf add_argument übergeben? –

+1

FWIW, wenn ich 'usage: foo.py [setupFile] [name date location]' gesehen habe, wäre meine Interpretation des args-Formats _completely_ anders als das, was du beschreibst. – NPE

+0

@ NPE: Guter Punkt. welches format wäre sinnvoll, denkst du? –

Antwort

1

nicht ganz sicher, das ist, was Sie wollen, aber wenn ich Sie richtig verstanden:

if __name__ =='__main__': 
    def dem_args(*args): 
     if len(args) == 1: 
      if os.path.isfile(args[0]): 
       #go file 
      else: 
       #error regarding this being a bad filename or nonexistent file 
     elif len(args) == 3: 
      #try to process/raise errors regarding name, date, location 
     else: 
      #error reg. wrong number of arguments, possible arguments are either this or that 
3

Ich denke, das klarste Design argparse Verwendung ist:

parser = argparse.ArgumentParser() 
g = parser.add_mutually_exclusive_group() 
g.add_argument('--setup','-s',metavar='FILE',help='your help') 
g.add_argument('--name',nargs=3,metavar=('NAME','DATE','LOCATION'),hel 
    ...: p='your help') 

parser.print_help() pro duces:

usage: ipython3 [-h] [--setup FILE | --name NAME DATE LOCATION] 

optional arguments: 
    -h, --help   show this help message and exit 
    --setup FILE, -s FILE 
         your help 
    --name NAME DATE LOCATION 
         your help 

Ich habe die 1 or 3 Argumente Anforderung mit sich gegenseitig ausschließende optionals behandelt. Und verwendet metavar, um Klarheit zu den Argumenten hinzuzufügen. (Wie bereits in einer anderen aktuellen Frage erwähnt, funktioniert metavar nicht gut mit positionals.)

Eine andere Option ist die Verwendung subparsers. Das erfordert immer noch ein Schlüsselwort wie setup und name, nur sie werden ohne die -- eingegeben. Und die Hilfsstruktur für Subparser ist ganz anders.

+0

Ja, das Arbeiten mit mehreren Argumente sind wichtig. Aber interessant, ich wusste nicht über Gruppen! –

0

Ok, das mache ich gerade. Ich bringe das hier hin, damit Leute es kommentieren können, und falls es für die Nachwelt nützlich sein sollte.

Ich löse eigentlich ein zusätzliches Problem hier. Das Problem ist tatsächlich ein bisschen komplizierter als sogar ich spezifiziert habe.Weil es tatsächlich 3 Möglichkeiten gibt, das Programm zu starten, und ich möchte in der Lage sein, eine Option --help zu haben, um nur die Details für einen Typ anzugeben. Also möchte ich -h, -h 1 und -h 2 alle verschiedene Dinge tun.

Mein aktueller Code ist:

import argparse 

baseParser = argparse.ArgumentParser(add_help=False) 
baseParser.add_argument('-f', '--foo', help ='foo argument') 
baseParser.add_argument('-h', '--help', nargs='?' , const = 'all') 

parser1 = argparse.ArgumentParser(parents = [baseParser], add_help=False) 
parser1.add_argument('name', help='name argument (type 1)') 
parser1.add_argument('date', help='date argument') 
parser1.add_argument('location', help='location argument') 

setupParser=argparse.ArgumentParser(parents = [baseParser],add_help=False) 
setupParser.add_argument('setup', help='setup file') 

parser2 = argparse.ArgumentParser(parents = [baseParser],add_help=False) 
parser2.add_argument('name', help='name argument (type 2)') 
parser2.add_argument('baa', help='sheep?') 

realParser = argparse.ArgumentParser(parents=[baseParser], add_help=False) 
realParser.add_argument('ARGS', nargs = '*', help = 'positional arguments') 

args = realParser.parse_args() 
if args.help: 
    if args.help == 'all': 
     print 'This product can be used in multiple ways:' 
     print 'setup' 
     setupParser.print_usage() 
     print 'type1' 
     parser1.print_usage() 
     print'type2' 
     parser2.print_usage() 
     print 'use help [type] for more details' 
    elif args.help=='setup': 
     setupParser.print_help() 
    elif args.help=='1': 
     parser1.print_help() 
    else: 
     parser2.print_help() 
    exit(0) 
    #actually parse the args in args.ARGS, and work with that 
Verwandte Themen