Каков наилучший способ разбора аргументов командной строки? - PullRequest
202 голосов
/ 21 августа 2008

Что такое самый простой , tersest и самый гибкий метод или библиотека для анализа аргументов командной строки Python?

Ответы [ 15 ]

3 голосов
/ 21 августа 2008

Я предпочитаю optparse для getopt. Это очень декларативно: вы сообщаете ему названия опций и эффекты, которые они должны иметь (например, установка логического поля), и он возвращает вам словарь, заполненный в соответствии с вашими спецификациями.

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

2 голосов
/ 05 июля 2018

Argparse-код может быть длиннее, чем фактический код реализации!

Проблема, с которой я сталкиваюсь при использовании самых популярных опций разбора аргументов, заключается в том, что если ваши параметры являются лишь скромными, то код для их документирования становится непропорционально большим, что приносит им пользу.

Относительный новичок в сцене разбора аргументов (я думаю): plac .

Это делает некоторые признанные компромиссы с argparse, но использует встроенную документацию и оборачивается просто вокруг main() функции типа:

def main(excel_file_path: "Path to input training file.",
     excel_sheet_name:"Name of the excel sheet containing training data including columns 'Label' and 'Description'.",
     existing_model_path: "Path to an existing model to refine."=None,
     batch_size_start: "The smallest size of any minibatch."=10.,
     batch_size_stop:  "The largest size of any minibatch."=250.,
     batch_size_step:  "The step for increase in minibatch size."=1.002,
     batch_test_steps: "Flag.  If True, show minibatch steps."=False):
"Train a Spacy (http://spacy.io/) text classification model with gold document and label data until the model nears convergence (LOSS < 0.5)."

    pass # Implementation code goes here!

if __name__ == '__main__':
    import plac; plac.call(main)
2 голосов
/ 30 июня 2012

consoleargs заслуживает упоминания здесь. Он очень прост в использовании. Проверьте это:

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()

Теперь в консоли:

% 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 голосов
/ 24 июля 2018

Я расширил подход Эрко, чтобы учесть необходимые позиционные аргументы и необязательные аргументы. Они должны предшествовать аргументам -d, -v и т. Д.

Позиционные и необязательные аргументы могут быть получены с помощью PosArg (i) и OptArg (i, по умолчанию) соответственно. При обнаружении необязательного аргумента начальная позиция поиска параметров (например, -i) перемещается на 1 вперед, чтобы избежать «неожиданного» фатального исхода.

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) 
0 голосов
/ 09 апреля 2016

Вот метод, а не библиотека, которая, кажется, работает для меня.

Цели здесь должны быть краткими, каждый аргумент анализируется одной строкой, аргументы выстраиваются для удобства чтения, код прост и не зависит от каких-либо специальных модулей (только os + sys), предупреждает об отсутствии или Изящные неизвестные аргументы, используйте простой цикл for / range () и работают через python 2.x и 3.x

Показаны два переключателя (-d, -v) и два значения, управляемых аргументами (-i xxx и -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))

Целью NextArg () является возвращение следующего аргумента при проверке отсутствующих данных, а 'skip' пропускает цикл, когда используется NextArg (), сохраняя при этом флаг, разбирающий до одной строки.

...