358 Stimmen

Wie lassen sich Befehlszeilenargumente am besten auswerten?

Was ist das am einfachsten , am knappsten und die meisten flexibel Methode oder Bibliothek zum Parsen von Python-Befehlszeilenargumenten?

3voto

Chris Conway Punkte 54023

Ich bevorzuge optparse gegenüber getopt. Es ist sehr deklarativ: Sie teilen ihm die Namen der Optionen und die Auswirkungen mit, die sie haben sollen (z.B. das Setzen eines booleschen Feldes), und es gibt Ihnen ein Wörterbuch zurück, das entsprechend Ihren Angaben gefüllt ist.

http://docs.python.org/lib/module-optparse.html

3voto

Peter Hoffmann Punkte 52200

Ich denke, der beste Weg für größere Projekte ist optparse, aber wenn Sie nach einem einfachen Weg suchen, vielleicht http://werkzeug.pocoo.org/documentation/script ist etwas für Sie.

from werkzeug import script

# actions go here
def action_foo(name=""):
    """action foo does foo"""
    pass

def action_bar(id=0, title="default title"):
    """action bar does bar"""
    pass

if __name__ == '__main__':
    script.run()

Im Grunde genommen ist also jede Funktion action_* der Kommandozeile ausgesetzt und eine schöne Hilfemeldung wird kostenlos generiert.

python foo.py 
usage: foo.py <action> [<options>]
       foo.py --help

actions:
  bar:
    action bar does bar

    --id                          integer   0
    --title                       string    default title

  foo:
    action foo does foo

    --name                        string

0 Stimmen

Ich habe ein kleines Paket entwickelt, das die automatische Erstellung von Argumenten nutzt: declarative_parser . Wenn man mit Werkzeugen arbeitet, kann es natürlich besser sein, die werkzung.script . Ich bin jedenfalls ein großer Fan eines solchen Ansatzes.

3voto

stalk Punkte 11616

Konsolenargumente verdient es, hier erwähnt zu werden. Es ist sehr einfach zu benutzen. Probieren Sie es aus:

from consoleargs import command

@command
def main(url, name=None):
  """
  :param url: Remote URL 
  :param name: File name
  """
  print """Downloading url '%r' into file '%r'""" % (url, name)

if __name__ == '__main__':
  main()

Jetzt in der Konsole:

% python demo.py --help
Usage: demo.py URL [OPTIONS]

URL:    Remote URL 

Options:
    --name -n   File name

% python demo.py http://www.google.com/
Downloading url ''http://www.google.com/'' into file 'None'

% python demo.py http://www.google.com/ --name=index.html
Downloading url ''http://www.google.com/'' into file ''index.html''

0 Stimmen

Ich habe einen ähnlichen Ansatz in deklarative-parser siehe Ableitung von Argumenten (Typisierung, docstrings, kwargs) in den Dokumenten. Hauptunterschiede: python3, Typ-Hinweise, pip-installierbar.

1 Stimmen

Letztes Engagement im Jahr 2012

1voto

erco Punkte 272

Hier ist eine Methode, keine Bibliothek, die für mich zu funktionieren scheint.

Die Ziele hier sind, kurz und bündig zu sein, jedes Argument in einer einzigen Zeile zu parsen, die Argumente für die Lesbarkeit aufzureihen, der Code ist einfach und hängt nicht von irgendwelchen speziellen Modulen ab (nur os + sys), warnt vor fehlenden oder unbekannten Argumenten, verwendet eine einfache for/range()-Schleife, und funktioniert in Python 2.x und 3.x

Gezeigt werden zwei Toggle-Flags (-d, -v) und zwei durch Argumente gesteuerte Werte (-i xxx und -o xxx).

import os,sys

def HelpAndExit():
    print("<<your help output goes here>>")
    sys.exit(1)

def Fatal(msg):
    sys.stderr.write("%s: %s\n" % (os.path.basename(sys.argv[0]), msg))
    sys.exit(1)

def NextArg(i):
    '''Return the next command line argument (if there is one)'''
    if ((i+1) >= len(sys.argv)):
        Fatal("'%s' expected an argument" % sys.argv[i])
    return(1, sys.argv[i+1])

### MAIN
if __name__=='__main__':

    verbose = 0
    debug   = 0
    infile  = "infile"
    outfile = "outfile"

    # Parse command line
    skip = 0
    for i in range(1, len(sys.argv)):
        if not skip:
            if   sys.argv[i][:2] == "-d": debug ^= 1
            elif sys.argv[i][:2] == "-v": verbose ^= 1
            elif sys.argv[i][:2] == "-i": (skip,infile)  = NextArg(i)
            elif sys.argv[i][:2] == "-o": (skip,outfile) = NextArg(i)
            elif sys.argv[i][:2] == "-h": HelpAndExit()
            elif sys.argv[i][:1] == "-":  Fatal("'%s' unknown argument" % sys.argv[i])
            else:                         Fatal("'%s' unexpected" % sys.argv[i])
        else: skip = 0

    print("%d,%d,%s,%s" % (debug,verbose,infile,outfile))

Das Ziel von NextArg() ist es, das nächste Argument zurückzugeben und dabei auf fehlende Daten zu prüfen. Mit 'skip' wird die Schleife übersprungen, wenn NextArg() verwendet wird, so dass sich das Parsen der Flagge auf Einzeiler beschränkt.

1voto

Erik Punkte 1

Ich habe Erco's Ansatz erweitert, um erforderliche Positionsargumente und optionale Argumente zuzulassen. Diese sollten den Argumenten -d, -v usw. vorangestellt werden.

Positionale und optionale Argumente können mit PosArg(i) bzw. OptArg(i, default) abgerufen werden. Wenn ein optionales Argument gefunden wird, wird die Startposition der Suche nach Optionen (z.B. -i) um 1 nach vorne verschoben, um ein "unerwartetes" fatales Ergebnis zu vermeiden.

import os,sys

def HelpAndExit():
    print("<<your help output goes here>>")
    sys.exit(1)

def Fatal(msg):
    sys.stderr.write("%s: %s\n" % (os.path.basename(sys.argv[0]), msg))
    sys.exit(1)

def NextArg(i):
    '''Return the next command line argument (if there is one)'''
    if ((i+1) >= len(sys.argv)):
        Fatal("'%s' expected an argument" % sys.argv[i])
    return(1, sys.argv[i+1])

def PosArg(i):
    '''Return positional argument'''
    if i >= len(sys.argv):
        Fatal("'%s' expected an argument" % sys.argv[i])
    return sys.argv[i]

def OptArg(i, default):
    '''Return optional argument (if there is one)'''
    if i >= len(sys.argv):
        Fatal("'%s' expected an argument" % sys.argv[i])
    if sys.argv[i][:1] != '-':
        return True, sys.argv[i]
    else:
        return False, default

### MAIN
if __name__=='__main__':

    verbose = 0
    debug   = 0
    infile  = "infile"
    outfile = "outfile"
    options_start = 3

    # --- Parse two positional parameters ---
    n1 = int(PosArg(1))
    n2 = int(PosArg(2))

    # --- Parse an optional parameters ---
    present, a3 = OptArg(3,50)
    n3 = int(a3)
    options_start += int(present)

    # --- Parse rest of command line ---
    skip = 0
    for i in range(options_start, len(sys.argv)):
        if not skip:
            if   sys.argv[i][:2] == "-d": debug ^= 1
            elif sys.argv[i][:2] == "-v": verbose ^= 1
            elif sys.argv[i][:2] == "-i": (skip,infile)  = NextArg(i)
            elif sys.argv[i][:2] == "-o": (skip,outfile) = NextArg(i)
            elif sys.argv[i][:2] == "-h": HelpAndExit()
            elif sys.argv[i][:1] == "-":  Fatal("'%s' unknown argument" % sys.argv[i])
            else:                         Fatal("'%s' unexpected" % sys.argv[i])
        else: skip = 0

    print("Number 1 = %d" % n1)
    print("Number 2 = %d" % n2)
    print("Number 3 = %d" % n3)
    print("Debug    = %d" % debug)
    print("verbose  = %d" % verbose)
    print("infile   = %s" % infile)
    print("outfile  = %s" % outfile)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X