【问题标题】:how to make argument optional in python argparse如何在python argparse中使参数可选
【发布时间】:2013-03-23 03:54:29
【问题描述】:

我想让 myprog 的这些调用工作,而不是其他的。

$ python3 myprog.py -i infile -o outfile
$ python3 myprog.py -o outfile
$ python3 myprog.py -o
$ python3 myprog.py 

我特别想让指定 infile 而不是 outfile 成为非法。

在第三种情况下,假定输出文件的默认名称为“out.json”。在第二种、第三种和第四种情况下,假定输入文件的默认名称为“file.n.json”,其中 n 是整数版本号。在第四种情况下,输出文件将是“file.n+1.json”,其中 n+1 是比输入文件上的版本大一号的版本号。我的代码的相关部分是:

import argparse

parser = argparse.ArgumentParser(description="first python version")
parser.add_argument('-i', '--infile', nargs=1, type=argparse.FileType('r'), help='input file, in JSON format')
parser.add_argument('-o', '--outfile', nargs='?', type=argparse.FileType('w'), default='out.json', help='output file, in JSON format')

args = parser.parse_args()

print("Here's what we saw on the command line: ")
print("args.infile",args.infile)
print("args.outfile",args.outfile)

if args.infile and not args.outfile:
    parser.error("dont specify an infile without specifying an outfile")
elif not args.infile:
    print("fetching infile")
else: # neither was specified on the command line
    print("fetching both infile and outfile")

问题是,当我运行时

$ python3 myprog.py -i infile.json

我得到的不是我希望的解析器错误:

Here's what we saw on the command line: 
args.infile [<_io.TextIOWrapper name='infile.json' mode='r' encoding='UTF-8'>]
args.outfile <_io.TextIOWrapper name='out.json' mode='w' encoding='UTF-8'>
fetching both infile and outfile

...这表明即使命令行上没有“-o”,它的行为就像有一样。

【问题讨论】:

  • 第三种情况和第四种情况有什么区别? -o 代表什么?
  • 第四种情况将使用默认的 infile 和 outfile 名称(特别是 file.n.json 和 file.n+1.json,即嵌入了版本号的文件)。这些与“out.json”不同,后者是“-o”选项的第三种情况。我已经修改了上面的文字以表明这一点。
  • 第 4 种情况应该如何工作,因为 --input 选项没有默认值?

标签: python argparse


【解决方案1】:

作为所选答案的附加组件:

在不指定文件的情况下运行-o 的选项可以使用const 结合nargs='?' 来完成。

来自docs

当使用选项字符串调用 add_argument() 时(如 -f 或 --foo) 和 nargs='?'。这将创建一个可以遵循的可选参数 通过零个或一个命令行参数。解析命令行时, 如果遇到没有命令行参数的选项字符串 在它之后,将假定 const 的值。见 示例的 nargs 描述。

示例(字符串类型):

parser.add_argument('-o', '--outfile', nargs='?', const='arg_was_not_given', help='output file, in JSON format')

args = parser.parse_args()

if args.outfile is None:
    print('Option not given at all')
elif args.outfile == 'arg_was_not_given':
    print('Option given, but no command-line argument: "-o"')
elif:
    print('Option and command-line argument given: "-o <file>"')

【讨论】:

    【解决方案2】:

    您为输出文件指定了默认参数。

    parser.add_argument('-o', '--outfile', nargs='?', type=argparse.FileType('w'), default='out.json', help='output file, in JSON format')
    

    如果在命令行中没有指定-o 选项,arg 解析器会插入默认参数。

    将其更改为:

    parser.add_argument('-o', '--outfile', nargs='?', type=argparse.FileType('w'), help='output file, in JSON format')
    

    一切都会如你所愿。


    如果您希望能够指定 -o,但没有文件名,您可能需要类似:

    out_file = args.out if args.out is not None else 'json.out'

    如果您指定不带参数的-o,我不确定相关参数是None 还是''(即空字符串)——我怀疑它是None,但我不知道不确定。您必须对其进行测试才能确定。

    如果没有 argparse 的额外逻辑,我不知道该怎么做。

    【讨论】:

    • 这几乎正是我想要的。剩下的问题是我希望$ python3 myprog.py -o 表现得好像我运行了$ python3 myprog.py -o out.json。你能建议如何做到这一点吗?
    • 谢谢!我原以为我可以用 argparse 做到这一点。
    • 这个答案忽略了问题中第三种情况的要求。请参阅 maximi 的答案,了解如何使用 argparse 实现第三种情况。最后一个赋值甚至不是有效的 Python 语法。
    猜你喜欢
    • 2016-05-30
    • 2019-07-12
    • 2017-11-28
    • 2019-11-17
    • 2017-01-14
    • 2018-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多