Вопрос по python – Как читать / обрабатывать аргументы командной строки?

527

Я изначально программист на Си. Я видел множество трюков и "взломов" читать много разных аргументов.

Как программисты Python могут это сделать?

Related

Используйте docopt (см. Ответ @ ralbatross наstackoverflow.com/a/14790373/116891). Я пробовал все по-другому, и действительно, docopt - единственный, который я буду использовать в дальнейшем. Pat
Я не думаю, что есть один единственный лучший способ. argparse является стандартным и функциональным. Докопт очень элегантный, но не в стандартной библиотеке. Для очень легкого использования вы можетеmake function default values handle comand line argument defaults for you. Simon Hibbs

Ваш Ответ

17   ответов
3

Argh, Он основан на argparse и позволяет писать такие вещи, как:

import argh

# declaring:

def echo(text):
    "Returns given word as is."
    return text

def greet(name, greeting='Hello'):
    "Greets the user with given name. The greeting is customizable."
    return greeting + ', ' + name

# assembling:

parser = argh.ArghParser()
parser.add_commands([echo, greet])

# dispatching:

if __name__ == '__main__':
    parser.dispatch()

Он автоматически сгенерирует справку и т. Д., И вы можете использовать декораторы для предоставления дополнительных указаний о том, как должен работать анализ arg.

Это лучшее решение. С помощьюargh легче, чем другие библиотеки или использованиеsys.
Я хотел понравитьсяargh но это не особенно подходит для сценариев, в которых ваше максимальное желание не состоит в том, чтобы иметь команду с подкомандами.
@tripleee YMMV, но я обнаружил, что это было скорее дефектом в документации, чем в самой библиотеке. Кажется вполне возможным иметьdef frobnicate_spleches(...) определить функцию, которая делает все, что делает ваш скрипт, затем делатьif __name__ == '__main__': argh.dispatch_command(frobnicate_spleches) в конце файла.
356

argparse (документы):

Вот пример:

from argparse import ArgumentParser

parser = ArgumentParser()
parser.add_argument("-f", "--file", dest="filename",
                    help="write report to FILE", metavar="FILE")
parser.add_argument("-q", "--quiet",
                    action="store_false", dest="verbose", default=True,
                    help="don't print status messages to stdout")

args = parser.parse_args()

argparse поддерживает (между прочим):

Multiple options in any order. Short and long options. Default values. Generation of a usage help message.
Документация Python предлагает использоватьargparse вместо optparse.
optparse - один из лучших; getopt стар и действительно должен считаться устаревшим.
Да, это лучшие. Так как они являются частью стандартной библиотеки, вы можете быть уверены, что они будут доступны и просты в использовании. Optparse, в частности, мощный и простой.
посколькуoptparse устарел, тот, кто задал вопрос, больше не является участником переполнения стека, и это принятый ответ на очень заметный вопрос - пожалуйста, рассмотрите возможность полностью переписать ваш пример кода для использования stdlibargparse вместо.
на данный момент (12/2011) argparse теперь считается лучшим вариантом, чем optparse, правильно?
34

main.py:

import sys

first_name = sys.argv[1]
last_name = sys.argv[2]
print("Hello " + first_name + " " + last_name)

Тогда бегиpython main.py James Smith

произвести следующий вывод:

Hello James Smith

Я не согласен с тем, что мое использование менее реалистично. Притворяться, что вашей программе нужно знать точное имя и фамилию человека, чтобы запустить сценарий в бизнесе, где люди могут иметь несколько имен и фамилий? Если у Джеймса Смита в качестве дополнительного имени или фамилии указан Джозеф, то как будет отличаться, является ли Джозеф дополнительным именем или фамилией, если вы толькоpython main.py "James Joseph Smith"? Если вас интересует индекс за пределами границ, вы можете добавить проверку на количество предоставленных аргументов. Менее реалистично или нет, мой пример показывает, как обрабатывать несколько аргументов.
Более реалистичное использование будетpython main.py "James Smith" который ставитJames Smith вsys.argv[1] и производитIndexError когда вы пытаетесь использовать несуществующееsys.argv[2], Поведение цитирования будет в некоторой степени зависеть от того, с какой платформы и оболочки вы запускаете Python.
125

Просто ходить вокруг евангелизации дляargparse что лучше дляэти причины .. по существу:

(copied from the link)

  • argparse module can handle positional and optional arguments, while optparse can handle only optional arguments

  • argparse isn’t dogmatic about what your command line interface should look like - options like -file or /file are supported, as are required options. Optparse refuses to support these features, preferring purity over practicality

  • argparse produces more informative usage messages, including command-line usage determined from your arguments, and help messages for both positional and optional arguments. The optparse module requires you to write your own usage string, and has no way to display help for positional arguments.

  • argparse supports action that consume a variable number of command-line args, while optparse requires that the exact number of arguments (e.g. 1, 2, or 3) be known in advance

  • argparse supports parsers that dispatch to sub-commands, while optparse requires setting allow_interspersed_args and doing the parser dispatch manually

И мой личный фаворит:

  • argparse allows the type and action parameters to add_argument() to be specified with simple callables, while optparse requires hacking class attributes like STORE_ACTIONS or CHECK_METHODS to get proper argument checking
@osman Этот нежныйtutorial на argparse может помочь ...
Теперь это часть стандартного Python с 2.7 и 3.2 :)
Просто краткость: argparse документация также безумно, безумно сложна. Вы не можете получить простой ответ на вопрос «Как заставить аргумент командной строки принимать одно значение и как получить к нему доступ». & Lt; / схватывание & GT;
Что такое «необязательные аргументы»? Вы говорите, что они не в порядке. Я думал, что это были аргументы, которые могут или не могут быть предоставлены, но вы сказали, что они в optparse, продолжая говорить, что "optparse требует, чтобы точное количество аргументов было известно заранее". Так что либо ваше определение & quot; необязательный аргумент & quot; отличается от того, что я думал, или ваш ответ не соответствует сам по себе.
@ArtOfWarfare & quot; необязательные аргументы & quot; в этом контексте, вероятно, означает аргументы, указанные с аргументами типа опции, такими как-f или же--fooв то время как «точное количество аргументов должно быть известно заранее»; предположительно означает позиционные аргументы, данные без каких-либо предшествующих опционных флагов.
2
import argparse

parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
                   help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
                   const=sum, default=max,
                   help='sum the integers (default: find the max)')

args = parser.parse_args()
print(args.accumulate(args.integers))

Assuming the Python code above is saved into a file called prog.py
$ python prog.py -h

Ref-link: https://docs.python.org/3.3/library/argparse.html
4

docopt как простая альтернатива этим другим.

docopt - это новый проект, который работает, анализируя ваше сообщение об использовании --help, а не требует, чтобы вы все реализовали самостоятельно. Вы просто должны поместить свое сообщение об использовании в формате POSIX.

7

щелчок более интуитивно понятный, требует меньше шаблонного и, по крайней мере, такой же мощный, как argparse.

Единственный недостаток, с которым я сталкивался до сих пор, заключается в том, что вы не можете много настраивать, чтобы помочь страницам, но это обычно не является обязательным требованием иdocopt кажется четким выбором, когда это так.

7

optparse & quot; Модуль optparse устарел и больше не будет разрабатываться; развитие будет продолжено сargparse . Модуль & Quot;

0

Мое решениеentrypoint2, Пример:

from entrypoint2 import entrypoint
@entrypoint
def add(file, quiet=True): 
    ''' This function writes report.

    :param file: write report to FILE
    :param quiet: don't print status messages to stdout
    '''
    print file,quiet

текст справки:

usage: report.py [-h] [-q] [--debug] file

This function writes report.

positional arguments:
  file         write report to FILE

optional arguments:
  -h, --help   show this help message and exit
  -q, --quiet  don't print status messages to stdout
  --debug      set logging level to DEBUG
19

но мне действительно нравится то направление, которое берет Саймон Уиллисон со своим недавно представленнымoptfunc библиотека. Работает:

"introspecting a function definition (including its arguments and their default values) and using that to construct a command line argument parser."

Так, например, это определение функции:

def geocode(s, api_key='', geocoder='google', list_geocoders=False):

превращается в этот необязательный текст справки:

    Options:
      -h, --help            show this help message and exit
      -l, --list-geocoders
      -a API_KEY, --api-key=API_KEY
      -g GEOCODER, --geocoder=GEOCODER
46

docopt Библиотека действительно гладкая. Он создает аргумент dict из строки использования для вашего приложения.

Например, из документа docopt:

"""Naval Fate.

Usage:
  naval_fate.py ship new <name>...
  naval_fate.py ship <name> move <x> <y> [--speed=<kn>]
  naval_fate.py ship shoot <x> <y>
  naval_fate.py mine (set|remove) <x> <y> [--moored | --drifting]
  naval_fate.py (-h | --help)
  naval_fate.py --version

Options:
  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.

"""
from docopt import docopt


if __name__ == '__main__':
    arguments = docopt(__doc__, version='Naval Fate 2.0')
    print(arguments)
Это быстро стало моим любимым способом. Это синтаксический анализ строки, поэтому он хрупкий, но хрупкий.all in one place и вы можете просмотреть свою логику вtry.docopt.org , Необязательные и взаимоисключающие аргументы делаются действительно элегантно.
Я отчаянно хочу увидеть остальную часть кода для naval_fate.py
8

try:
    opts, args = getopt.getopt(sys.argv[1:], 'h', ['help'])
except getopt.GetoptError, err: 
    usage(err)

for opt, arg in opts:
    if opt in ('-h', '--help'): 
        usage()

if len(args) != 1:
    usage("specify thing...")

В последнее время я добавлял к этому что-то похожее, чтобы сделать вещи менее многословными (например, сделать «-h» неявным).

23
#set default args as -h , if no args:
if len(sys.argv) == 1: sys.argv[1:] = ["-h"]
65

Существует такжеargparse stdlib module («наложение» на stdlib)optparse модуль). Пример извведение в argparse:

# script.py
import argparse

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument(
        'integers', metavar='int', type=int, choices=range(10),
         nargs='+', help='an integer in the range 0..9')
    parser.add_argument(
        '--sum', dest='accumulate', action='store_const', const=sum,
        default=max, help='sum the integers (default: find the max)')

    args = parser.parse_args()
    print(args.accumulate(args.integers))

Использование:

$ script.py 1 2 3 4
4

$ script.py --sum 1 2 3 4
10
его просто скопировать и вставить
@ blitu12345 на момент публикации моего ответа не было никаких других ответов, в которых упоминается argparse. Сам модуль не был в stdlib & # xB6; Что вы имеете против примеров кода из документации? Как вы думаете, почему необходимо придумывать свои собственные примеры вместо примеров, предоставленных автором модуля? И я не люблю ответы, содержащие только ссылки (я не одинок).
«Люди, пришедшие сюда, уже имели представление о том, что в документации» - яhighly сомневаюсь в этом предположении. как-то.
Люди, приезжающие сюда, уже имели представление о том, что в документации и будут здесь только для дальнейшего прояснения темы. То же самое было в моем случае, но то, что я действительно нашел здесь, это копия и вставка из оригинальной документации.
482
import sys

print("\n".join(sys.argv))

sys.argv список, содержащий все аргументы, переданные сценарию в командной строке

В принципе,

import sys
print(sys.argv[1:])
Для действительно простых вещей, это путь, хотя вы, вероятно, хотите использовать толькоsys.argv[1:] (избегает имени скрипта).
Это работает, когда я запускаю его на Python 2.7.13
Это для Python3
4

Вас может заинтересовать небольшой модуль Python, который я написал, чтобы сделать обработку аргументов командной строки еще проще (с открытым исходным кодом и бесплатное использование) -Commando

Уже есть другой модуль синтаксического анализа командной строки с именем Commando:github.com/lakshmivyas/commando, Оборачивает argparse с помощью декораторов.
переосмысление питона и колеса
48

sys.argv, Это напечатает имя скрипта в качестве первого аргумента и все остальные параметры, которые вы передаете ему.

import sys

for arg in sys.argv:
    print arg

Похожие вопросы