Обработка параметров командной строки в префиксной нотации в Python

Я пытаюсь проанализировать командную строку в Python, который похож на следующее:

$ ./command -o option1 arg1 -o option2 arg2 arg3

Другими словами, команда берет неограниченное количество аргументов, и каждому аргументу можно дополнительно предшествовать с -o опция, которая имеет отношение конкретно к тому аргументу. Я думаю, что это называют "префиксной нотацией".

В Оболочке Bourne я сделал бы что-то как следующее:

while test -n "$1"
do
    if test "$1" = '-o'
    then
        option="$2"
        shift 2
    fi
    # Work with $1 (the argument) and $option (the option)
    # ...
    shift
done

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

Пытаясь реализовать этот шаблон в Python, мое первое предположение должно было использовать pop(), поскольку это - в основном операция стека. Но я предполагаю, что это не будет работать также над Python потому что список аргументов в sys.argv находится в неправильном порядке и должен был бы быть обработан как очередь (т.е. поп слева). Я считал, что списки не оптимизированы для использования в качестве очередей в Python.

Так, мои идеи: преобразовать argv к a collections.deque и используйте popleft(), реверс argv использование reverse() и используйте pop(), или возможно просто работа с самими международными индексами списка.

Кто-либо знает о лучшем способе сделать это, иначе какая из моих идей была бы наиболее успешной практикой в Python?

7
задан ejm 14 May 2010 в 02:57
поделиться

4 ответа

другой модуль stdlib: argparse

p = argparse.ArgumentParser()
p.add_argument('-o', action='append')
for i in range(1, 4): p.add_argument('arg%d' % i)
args = p.parse_args('-o option1 arg1 -o option2 arg2 arg3'.split())
print args
# -> Namespace(arg1='arg1', arg2='arg2', arg3='arg3', o=['option1', 'option2'])
7
ответ дан 6 December 2019 в 08:14
поделиться

Не нужно изобретать велосипед: модуль getopt предназначен именно для этого. Если это вам не подходит, попробуйте модуль optparse , который более гибкий, но более сложный.

2
ответ дан 6 December 2019 в 08:14
поделиться

Вы можете сделать

argv.pop(0)

, который снимает первый элемент и возвращает его. Хотя, вероятно, это неэффективно. Может быть. Я не уверен, как argv реализован под капотом. (Опять же, если эффективность , что важна, почему вы используете Python?)

Однако более питоническим решением было бы перебирать список без выталкивания элементов. Примерно так:

o_flag = False
for a in argv:
    if a == '-o':
        o_flag = True
        continue
    # do whatever
    o_flag = False

Также я думаю, что заслуживает упоминания модуль optparse ; он довольно стандартен для обработки опций и аргументов в программах Python, хотя может оказаться излишним для этой задачи, поскольку у вас уже есть несколько совершенно функциональных решений.

5
ответ дан 6 December 2019 в 08:14
поделиться

Что-то вроде:

for arg in sys.argv[1:]:
  # do something with arg

должно вам подойти. Если вы не ожидаете чрезвычайно большого количества аргументов, я бы выбрал самый простой код (и не слишком беспокоился о производительности). Argv [1:] игнорирует это первое значение argv, которое будет именем сценария.

2
ответ дан 6 December 2019 в 08:14
поделиться
Другие вопросы по тегам:

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