Python argparse, значение после позиционного аргумента - PullRequest
0 голосов
/ 27 января 2019

Итак, я пишу эту очень маленькую программу для выполнения запросов http и отправки сообщений.Запросы следующие:

requestApp.py help
requestApp.py help get
requestApp.py help post
requestApp.py get [-v] [-h key:value] URL
requestApp.py post [-v] [-h key:value] [-d inline-data] [-f file] URL

Как видите, аргументы -v, -h, -d, -f, URL являются необязательными.Аргументы get и post не являются обязательными.Я покажу вам фрагмент моей программы, который имеет отношение к этой ситуации:

parser = argparse.ArgumentParser(description='httpc is a curl-like application but supports HTTP protocol only.')
parser.add_argument('command', type=str, help=help_output())
parser.add_argument('url', action='store_true', help='The URL that will be provided to perform the requested command.')
parser.add_argument('-v', '--verbose', action='store_true')

Аргумент command будет help, get или post, а аргумент url не требует пояснений.Мой вопрос связан со второй и третьей командами выше, а именно:

requestApp.py help get
requestApp.py help post

Как я могу убедиться, что при наборе help get, get не будет зарегистрирован в URL (то же самое для help post).Кроме того, когда я включаю URL-адрес, я хочу, чтобы он сохранялся внутри аргумента URL-адреса.Должен ли я вручную оценивать аргументы, передаваемые через операторы if?Или есть лучший способ сделать это?

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Возможно, самое близкое решение argparse, по крайней мере, без прохождения маршрута субпарсера, может быть:

import argparse
import sys
print(sys.argv)
parser = argparse.ArgumentParser()
parser.add_argument('-k', '--keyvalue')
parser.add_argument('-v', '--verbose', action='store_true')
parser.add_argument('-d', '--data')
parser.add_argument('-f', '--file')
parser.add_argument('pos1', choices = ['help', 'get', 'post'])
parser.add_argument('pos2')

args = parser.parse_args()
print(args)

Полученная помощь:

1744:~/mypy$ python stack54383659.py get aurl -h
['stack54383659.py', 'get', 'aurl', '-h']
usage: stack54383659.py [-h] [-k KEYVALUE] [-v] [-d DATA] [-f FILE]
                        {help,get,post} pos2

positional arguments:
  {help,get,post}
  pos2

optional arguments:
  -h, --help            show this help message and exit
  -k KEYVALUE, --keyvalue KEYVALUE
  -v, --verbose
  -d DATA, --data DATA
  -f FILE, --file FILE

Подходитне идеально.Например, вы можете дать help, но вы можете указать -h.2-е позиционное значение может быть любой строкой, «get», действительным URL или чем-то еще.Ваш собственный код должен подтвердить это.Бит key:value требует вашего собственного анализа.

При анализе argparse синтаксический анализ optionals может происходить в любом порядке.Два позиционера должны быть в указанном порядке (относительно друг друга).


В более новых питонах я могу изменить последний позиционер на «необязательный» и использовать новый синтаксический анализатор intermixed.Это позволило бы мне просто дать «помощь» (или просто «получить»):

parser.add_argument('pos2', nargs='?')
args = parser.parse_intermixed_args()

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

Другой подход заключается в определении всех отмеченных аргументов и использовании parse_known_args.Значения, не являющиеся флагами, будут в списке extras, который вы можете анализировать по своему усмотрению.Старые парсеры, такие как optparse, делали это по существу.argparse добавлена ​​ограниченная возможность обрабатывать позиционные аргументы, но строго по положению, а не по значению.

0 голосов
/ 27 января 2019

Это довольно сложно сделать, используя argparse, вот как это сделать, используя docopt, docopt анализирует шаблон использования и возвращает словарь:

"""
Usage:
    requestApp help [get|post]
    requestApp get [-v] [-k=key:value] <URL>
    requestApp post [-v] [-k=key:value] [-d=data] [-f file] <URL>

Options:
    -v --verbose       This is verbose mode
    -d=data            This option does this
    -k=key:value       This one does that
    -f file            This one is magic
"""

from docopt import docopt

ARGS = docopt(__doc__)

Например, с помощью requestApp.py post -k hello:world -f myfile.txt google.com docopt вернет:

{
  "--verbose": false, 
  "-d": None, 
  "-f": "myfile.txt", 
  "-k": "hello:world", 
  "<URL>": "google.com", 
  "get": false, 
  "help": false, 
  "post": true
}

Затем вы можете сделать:

if ARGS['help']:
    if ARGS['get']: pass                # requestApp help get
    else if ARGS['post']: pass          # requestApp help post
    else: pass                          # requestApp help
    exit()

if ARGS['get']: pass                    # requestApp get
else if ARGS['post']: pass              # requestApp post

if ARGS['--verbose']: print("this is just the beginning") 

-h - это зарезервированная опция по умолчанию (для справки), которая заставляет docopt возвращать шаблон использования ивыход.docopt вернет шаблон использования в stdout и завершит работу, если вы попытаетесь использовать недопустимые команды, такие как requestApp help unicorn

...