Programing

인수없이 스크립트를 호출하면 Python Argparse와 함께 도움말 메시지 표시

lottogame 2020. 5. 10. 10:12
반응형

인수없이 스크립트를 호출하면 Python Argparse와 함께 도움말 메시지 표시


이것은 간단한 것일 수 있습니다. argparse를 사용하여 명령 줄 인수 / 옵션을 처리하는 프로그램이 있다고 가정합니다. 다음은 '도움말'메시지를 인쇄합니다.

./myprogram -h

또는:

./myprogram --help

그러나 인수없이 스크립트를 실행하면 아무것도하지 않습니다. 내가 원하는 것은 인수없이 호출 될 때 사용법 메시지를 표시하는 것입니다. 어떻게됩니까?


이 답변은 Google 그룹의 Steven Bethard 가 제공합니다 . 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에 인쇄하는 데 사용하십시오 .


클래스를 작성하는 대신 try / except를 대신 사용할 수 있습니다.

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

단점은 워크 플로가 더 명확하고 스텁 클래스가 필요 없다는 것입니다. 단점은 첫 번째 '사용'줄이 두 번 인쇄된다는 것입니다.

이것은 적어도 하나의 필수 주장이 필요합니다. 필수 인수가 없으면 명령 행에서 0 개의 인수를 제공하는 것이 유효합니다.


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)

스크립트를 실행하기 위해 지정해야하는 인수가있는 경우 다음 과 같이 ArgumentParser에 필요한 매개 변수를 사용하십시오 .

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

인수없이 스크립트를 실행하면 parse_args ()가 오류를보고합니다.


아래 add_subparsers언급 된 것처럼 (하위) 파서에 대한 기본 기능을 연결 하면 간단히 기본 작업으로 추가 할 수 있습니다.

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

위치 인수가 누락되어 예외가 발생하면 try-except를 추가하십시오.


내 버전을 더미에 던지기 :

import argparse

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

당신은 알 수 있습니다 parser.exit- sys파일에서 유일한 이유라면 가져 오기 줄을 저장하기 때문에 주로 그렇게 합니다 ...


가장 깨끗한 해결책은 명령 줄에 기본 인수가 없으면 수동으로 기본 인수를 전달하는 것입니다.

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

인수없이 호출되면 완전한 도움말 (짧은 사용법이 아님)을 인쇄합니다.


There are a pair of one-liners with sys.argv[1:] (a very common Python's idiom to refer the command line arguments, being sys.argv[0] the script's name) that can do the job.

The first one is self-explanatory, clean and pythonic:

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

The second one is a little hackier. Combining the previously evaluated fact that an empty list is False with the True == 1 and False == 0 equivalences you get this:

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

Maybe too many brackets, but pretty clear if a previous argument selection was made.

_, *av = sys.argv
args = parser.parse_args([None, ['-h']][not av])

parser.print_help()
parser.exit()

The parser.exit method also accept a status (returncode), and a message value (include a trailing newline yourself!).

an opinionated example, :)

#!/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

Example calls:

$ 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

Set your positional arguments with nargs, and check if positional args are empty.

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('file', nargs='?')
args = parser.parse_args()
if not args.file:
    parser.print_help()

Reference Python nargs


Here is another way to do it, if you need something flexible where you want to display help if specific params are passed, none at all or more than 1 conflicting arg:

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 ...

Cheers!


If your command is something where a user needs to choose some action, then use a mutually exclusive group with required=True.

This is kind of an extension to the answer given by pd321.

import argparse

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--batch", action='store', type=int,  metavar='pay_id')
group.add_argument("--list", action='store_true')
group.add_argument("--all", action='store_true', help='check all payments')

args=parser.parse_args()

if args.batch:
    print('batch {}'.format(args.batch))

if args.list:
    print('list')

if args.all:
    print('all')

Output:

$ python3 a_test.py
usage: a_test.py [-h] (--batch pay_id | --list | --all)
a_test.py: error: one of the arguments --batch --list --all is required

This only give the basic help. And some of the other answers will give you the full help. But at least your users know they can do -h

참고URL : https://stackoverflow.com/questions/4042452/display-help-message-with-python-argparse-when-script-is-called-without-any-argu

반응형