假设我有一个使用argparse处理命令行参数/选项的程序。下面将打印“帮助”信息:

./myprogram -h

or:

./myprogram --help

但是,如果我不带任何参数运行脚本,它什么都不会做。我想要它做的是在不带参数地调用它时显示用法消息。怎么做呢?


当前回答

可以使用try/except来代替编写类

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

好处是工作流更加清晰,并且不需要存根类。缺点是第一个“usage”行打印了两次。

这至少需要一个强制参数。如果没有强制参数,在命令行上提供零参数是有效的。

其他回答

这个答案来自谷歌groups的Steven Bethard。我在这里重新发布它,让没有谷歌账户的人更容易访问。

你可以重写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()

请注意,上面的解决方案将打印帮助消息每当出现错误 方法触发。例如,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。

如果你必须为脚本运行指定参数,使用ArgumentParser所需的参数,如下所示

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

如果脚本在没有任何参数的情况下运行,Parse_args()将报告错误。

这里有另一种方法来做,如果你需要一些灵活的东西,你想显示帮助,如果特定的参数被传递,没有或超过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 ...

干杯!

这种方法比大多数其他方法要优雅得多。与其重写error(),你可以通过包装parse_args()方法来更精确地控制行为:

import sys
import argparse


HelpFlags = ('help', '--help', '-h', '/h', '?', '/?', )


class ArgParser (argparse.ArgumentParser):
    
    def __init__(self, *args, **kws):
        super().__init__(*args, **kws)
    
    def parse_args(self, args=None, namespace=None):
        
        if args is None:
            args = sys.argv[1:]
        
        if len(args) < 1 or (args[0].lower() in HelpFlags):
            self.print_help(sys.stderr)
            sys.exit()
        
        return super().parse_args(args, namespace)
parser.print_help()
parser.exit()

解析器。Exit方法还接受一个状态(returncode)和一个消息值(包括一个尾随换行符自己!)。

举个固执己见的例子, :)

#!/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=64, message="\nSomething went wrong, --example condition was not set\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

Something went wrong, --example condition was not set
64
$ python3 ~/helloworld.py --example; echo $?
0