【问题标题】:Python argparse - Mutually exclusive group with default if no argument is givenPython argparse - 如果没有给出参数,则默认互斥组
【发布时间】:2016-11-25 05:59:10
【问题描述】:

我正在编写一个 Python 脚本来处理一个机器可读的文件并输出一份关于其中包含的数据的人类可读的报告。
我想提供将数据输出到stdout (-s)(默认情况下)或txt(-t)或csv(-c)文件的选项。我想要一个默认行为的开关,就像许多命令一样。

Usage: 而言,我希望看到类似script [-s | -c | -t] input file 的内容,如果没有传递任何参数,则将-s 设为默认值。

我目前有(对于相关的参数,简而言之):

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('-s', '--stdout', action='store_true')
group.add_argument('-c', '--csv', action='store_true')
group.add_argument('-t', '--txt', action='store_true')
args = parser.parse_args()

if not any((args.stdout, args.csv, args.txt)):
    args.stdout = True

因此,如果没有设置-s-t-c,则stdout (-s) 被强制为True,就像-s 已被传递一样。

有没有更好的方法来实现这一点?或者出于某种原因,另一种方法是否会被普遍认为“更好”?

注意:我使用的是 Python 3.5.1/2,我不担心与其他版本的兼容性,因为目前没有计划与其他人共享此脚本。只是为了让我的生活更轻松。

【问题讨论】:

  • 我知道这不适用于 每个 情况,但这听起来与 choices 选项的用途完全一样:parser.add_argument('--output', default='stdout', choices=['stdout', 'csv', 'txt'])

标签: python python-3.x argparse


【解决方案1】:

您可以让每个操作更新同一个变量,提供标准输出作为该变量的默认值。

考虑这个程序:

import argparse

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument(
    '-s', '--stdout', action='store_const', dest='type', const='s', default='s')
group.add_argument(
    '-c', '--csv', action='store_const', dest='type', const='c')
group.add_argument(
    '-t', '--txt', action='store_const', dest='type', const='t')
args = parser.parse_args()
print args

您的代码可能如下所示:

if args.type == 's':
    ofile = sys.stdout
elif args.type == 'c':
    ofile = ...
...

第一种选择:

与其随意选择.add_argument()s之一来指定默认类型,不如使用parser.set_defaults()指定默认类型。

import argparse

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('-s', '--stdout', action='store_const', dest='type', const='s')
group.add_argument('-c', '--csv', action='store_const', dest='type', const='c')
group.add_argument('-t', '--txt', action='store_const', dest='type', const='t')
parser.set_defaults(type='s')
args = parser.parse_args()
print args

第二种选择:

您可以将可调用对象存储到类型中,然后调用可调用对象,而不是将类型指定为枚举值:

import argparse

def do_stdout():
    # do everything that is required to support stdout
    print("stdout!")
    return
def do_csv():
    # do everything that is required to support CSV file
    print("csv!")
    return
def do_text():
    # do everything that is required to support TXT file
    print("text!")
    return

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group()
group.add_argument('-s', '--stdout', action='store_const', dest='type', const=do_stdout)
group.add_argument('-c', '--csv', action='store_const', dest='type', const=do_csv)
group.add_argument('-t', '--txt', action='store_const', dest='type', const=do_text)
parser.set_defaults(type=do_stdout)
args = parser.parse_args()
print args
args.type()

【讨论】:

  • 这里的想法是每个动作都写入同一个变量。您也可以在参数定义之外指定默认值:if args.type is None or args.type =='s': ofile = sys.stdout
  • 感谢您提供非常详细的回答。
【解决方案2】:

你可以用 sys.argv “作弊”:

import sys


def main():
    if len(sys.argv) == 2 and sys.argv[1] not in ['-s', '-c', '-t', '-h']:
        filename = sys.argv[1]
        print "mode : stdout", filename
    else:
        parser = argparse.ArgumentParser()
        group = parser.add_mutually_exclusive_group()
        group.add_argument('-s', '--stdout')
        group.add_argument('-c', '--csv')
        group.add_argument('-t', '--txt')
        args = parser.parse_args()
        if args.stdout:
            print "mode stdout :",  args.stdout
        if args.csv:
            print "mode csv :",  args.csv
        if args.txt:
            print "mode txt :",  args.txt

if __name__ == "__main__":
    main()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-13
    • 2020-07-29
    • 2021-12-20
    • 2015-04-09
    • 2020-03-15
    • 2012-12-04
    • 2013-12-28
    相关资源
    最近更新 更多