Вывести справочное сообщение с python argparse, когда скрипт вызывается без аргументов - PullRequest
184 голосов
/ 28 октября 2010

Это может быть простым. Предположим, у меня есть программа, которая использует argparse для обработки аргументов / опций командной строки. Следующее напечатает сообщение «помощь»:

./myprogram -h

или

./myprogram --help

Но, если я запускаю скрипт без каких-либо аргументов, он ничего не делает. Я хочу, чтобы он отображал сообщение об использовании, когда оно вызывается без аргументов. Как это сделать?

Ответы [ 11 ]

238 голосов
/ 28 октября 2010

Этот ответ приходит от Стивена Бетарда в группах Google .Я публикую его здесь, чтобы облегчить доступ людям без учетной записи Google.

Вы можете переопределить поведение по умолчанию метода error:

import argparse
import sys

class MyParser(argparse.ArgumentParser):
    def error(self, message):
        sys.stderr.write('error: %s\n' % message)
        self.print_help()
        sys.exit(2)

parser = MyParser()
parser.add_argument('foo', nargs='+')
args = parser.parse_args()

Обратите внимание, что приведенное выше решение будет печатать сообщение справки всякий раз, когда вызывается метод error.Например, test.py --blah также выведет сообщение справки, если --blah не является допустимым параметром.

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

import argparse
import sys

parser=argparse.ArgumentParser()
parser.add_argument('foo', nargs='+')
if len(sys.argv)==1:
    parser.print_help(sys.stderr)
    sys.exit(1)
args=parser.parse_args()

Обратите внимание, что parser.print_help() печатает на стандартный вывод по умолчанию.Как init_js предлагает , используйте parser.print_help(sys.stderr) для печати в stderr.

46 голосов
/ 27 марта 2015

Вместо написания класса вместо него можно использовать попытку / исключение

try:
    options = parser.parse_args()
except:
    parser.print_help()
    sys.exit(0)

Преимущество в том, что рабочий процесс более понятен, и вам не нужен класс-заглушка.Недостатком является то, что первая строка «использования» печатается дважды.

Для этого потребуется хотя бы один обязательный аргумент.Без обязательных аргументов указание нулевого аргумента в командной строке является допустимым.

19 голосов
/ 28 марта 2015

С помощью argparse вы можете сделать:

parser.argparse.ArgumentParser()
#parser.add_args here

#sys.argv includes a list of elements starting with the program
if len(sys.argv) < 2:
    parser.print_usage()
    sys.exit(1)
15 голосов
/ 17 июня 2016

Если у вас есть аргументы, которые должны быть указаны для запуска скрипта - используйте параметр required для ArgumentParser, как показано ниже: -

parser.add_argument('--foo', required=True)

parse_args () сообщит об ошибкеесли скрипт запускается без аргументов.

12 голосов
/ 15 ноября 2016

Если вы связываете функции по умолчанию для (под) синтаксических анализаторов, как указано в add_subparsers, вы можете просто добавить их как действие по умолчанию:

parser = argparse.ArgumentParser()
parser.set_defaults(func=lambda x: parser.print_usage())
args = parser.parse_args()
args.func(args)

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

9 голосов
/ 28 сентября 2015

Бросаю мою версию в кучу здесь:

import argparse

parser = argparse.ArgumentParser()
args = parser.parse_args()
if not vars(args):
    parser.print_help()
    parser.exit(1)

Вы можете заметить parser.exit - я в основном так делаю, потому что он сохраняет строку импорта, если это была единственная причина для sys в файле ...

5 голосов
/ 22 ноября 2017

Самым чистым решением будет ручная передача аргумента по умолчанию, если в командной строке не было указано ни одного:

parser.parse_args(args=None if sys.argv[1:] else ['--help'])

Полный пример:

import argparse, sys

parser = argparse.ArgumentParser()
parser.add_argument('--host', default='localhost', help='Host to connect to')
# parse arguments
args = parser.parse_args(args=None if sys.argv[1:] else ['--help'])

# use your args
print("connecting to {}".format(args.host))

Это выведет полную справку (некороткое использование) если вызывается без аргументов.

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

Есть пара однострочников с sys.argv[1:] (очень распространенная идиома Python для ссылки на аргументы командной строки, являющаяся sys.argv[0] именем скрипта), которая может выполнить эту работу.

Первыйодин говорит само за себя, чисто и питонно:

args = parser.parse_args(None if sys.argv[1:] else ['-h'])

Второй немного более хакерский.Комбинируя ранее оцененный факт, что пустой список равен False с эквивалентностями True == 1 и False == 0, вы получаете это:

args = parser.parse_args([None, ['-h']][not sys.argv[1:]])

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

_, *av = sys.argv
args = parser.parse_args([None, ['-h']][not av])
1 голос
/ 14 декабря 2017
parser.print_help()
parser.exit()

Метод parser.exit также принимает значение status (код возврата) и значение message (включая завершающий перевод строки самостоятельно!).

пример самоуверенный, :)

#!/usr/bin/env python3

""" Example argparser based python file
"""

import argparse

ARGP = argparse.ArgumentParser(
    description=__doc__,
    formatter_class=argparse.RawTextHelpFormatter,
)
ARGP.add_argument('--example', action='store_true', help='Example Argument')


def main(argp=None):
    if argp is None:
        argp = ARGP.parse_args()  # pragma: no cover

    if 'soemthing_went_wrong' and not argp.example:
        ARGP.print_help()
        ARGP.exit(status=128, message="\nI just don't know what went wrong, maybe missing --example condition?\n")


if __name__ == '__main__':
    main()  # pragma: no cover

Пример звонков:

$ python3 ~/helloworld.py; echo $?
usage: helloworld.py [-h] [--example]

 Example argparser based python file

optional arguments:
  -h, --help  show this help message and exit
  --example   Example Argument

I just don't know what went wrong, maybe missing --example condition?
128
$ python3 ~/helloworld.py --example; echo $?
0
0 голосов
/ 20 декабря 2017

Вот еще один способ сделать это, если вам нужно что-то гибкое, где вы хотите отобразить справку, если переданы определенные параметры, ни одного вообще или более 1 конфликтующего аргумента:

import argparse
import sys

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-d', '--days', required=False,  help="Check mapped inventory that is x days old", default=None)
    parser.add_argument('-e', '--event', required=False, action="store", dest="event_id",
                        help="Check mapped inventory for a specific event", default=None)
    parser.add_argument('-b', '--broker', required=False, action="store", dest="broker_id",
                        help="Check mapped inventory for a broker", default=None)
    parser.add_argument('-k', '--keyword', required=False, action="store", dest="event_keyword",
                        help="Check mapped inventory for a specific event keyword", default=None)
    parser.add_argument('-p', '--product', required=False, action="store", dest="product_id",
                        help="Check mapped inventory for a specific product", default=None)
    parser.add_argument('-m', '--metadata', required=False, action="store", dest="metadata",
                        help="Check mapped inventory for specific metadata, good for debugging past tix", default=None)
    parser.add_argument('-u', '--update', required=False, action="store_true", dest="make_updates",
                        help="Update the event for a product if there is a difference, default No", default=False)
    args = parser.parse_args()

    days = args.days
    event_id = args.event_id
    broker_id = args.broker_id
    event_keyword = args.event_keyword
    product_id = args.product_id
    metadata = args.metadata
    make_updates = args.make_updates

    no_change_counter = 0
    change_counter = 0

    req_arg = bool(days) + bool(event_id) + bool(broker_id) + bool(product_id) + bool(event_keyword) + bool(metadata)
    if not req_arg:
        print("Need to specify days, broker id, event id, event keyword or past tickets full metadata")
        parser.print_help()
        sys.exit()
    elif req_arg != 1:
        print("More than one option specified. Need to specify only one required option")
        parser.print_help()
        sys.exit()

    # Processing logic here ...

Ура! * * 1004

...