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

./myprogram -h

or:

./myprogram --help

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


当前回答

当调用add_subparsers方法时,将第一个位置参数保存为dest=,并在argparse初始化后检查值,如下所示:

介子

检查一下这个变量:

if not args.command:
    parser.print_help()
    parser.exit(1)  # If exit() - exit code will be zero (no error)

完整的例子:

#!/usr/bin/env python

""" doc """

import argparse
import sys

parser = argparse.ArgumentParser(description=__doc__)
subparsers = parser.add_subparsers(dest='command',
                                   help='List of commands')

list_parser = subparsers.add_parser('list',
                                    help='List contents')
list_parser.add_argument('dir', action='store',
                         help='Directory to list')

create_parser = subparsers.add_parser('create',
                                      help='Create a directory')
create_parser.add_argument('dirname', action='store',
                           help='New directory to create')
create_parser.add_argument('--read-only', default=False, action='store_true',
                           help='Set permissions to prevent writing to the directory')

args = parser.parse_args()

if not args.command:
    parser.print_help()
    parser.exit(1)

print(vars(args))  # For debug

其他回答

这并不好(因为会拦截所有错误),但是:

def _error(parser):
    def wrapper(interceptor):
        parser.print_help()

        sys.exit(-1)

    return wrapper

def _args_get(args=sys.argv[1:]):
    parser = argparser.ArgumentParser()

    parser.error = _error(parser)

    parser.add_argument(...)
    ...

下面是ArgumentParser类的错误函数的定义。

如您所见,下面的签名有两个参数。然而,类之外的函数对第一个参数self一无所知,因为粗略地说,这个参数是类的。

def _error(self, message):
    self.print_help()

    sys.exit(-1)

def _args_get(args=sys.argv[1:]):
    parser = argparser.ArgumentParser()

    parser.error = _error
    ...

将输出:

"AttributeError: 'str' object has no attribute 'print_help'"

你可以在_error函数中传递parser (self),通过调用它:

def _error(self, message):
    self.print_help()

    sys.exit(-1)

def _args_get(args=sys.argv[1:]):
    parser = argparser.ArgumentParser()

    parser.error = _error(parser)
    ...

但是如果你现在不想退出程序,返回它:

def _error(parser):
    def wrapper():
        parser.print_help()

        sys.exit(-1)

    return wrapper

尽管如此,解析器并不知道它已被修改。因此,当发生错误时,它将打印错误的原因(顺便说一下,这是一个本地化的翻译)。所以截取它:

def _error(parser):
    def wrapper(interceptor):
        parser.print_help()

        sys.exit(-1)

    return wrapper

现在,当发生错误时,解析器将打印错误的原因,您将拦截它,查看它,然后……扔掉。

如果你为(sub)解析器关联默认函数,就像在add_subparsers中提到的那样,你可以简单地将它作为默认动作添加:

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

如果由于缺少位置参数而引发异常,则添加try-except。

最简洁的解决方案是手动传递默认参数,如果没有在命令行中给出:

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

如果调用w/o参数,这将打印完整的帮助(而不是简短的用法)。

这种方法比大多数其他方法要优雅得多。与其重写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)

如果您的命令是用户需要选择某些操作的命令,则使用互斥组required=True。

这是对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')

输出:

$ python3 a_test.py 用法:a_test.py [h](——批pay_id | - |列表) A_test.py: error:参数之一——batch——list——all是必需的

这只是基本的帮助。其他的一些答案会给你充分的帮助。但至少你的用户知道他们可以做-h