【问题标题】:Conditional command line arguments in Python using argparsePython中使用argparse的条件命令行参数
【发布时间】:2012-03-19 08:08:08
【问题描述】:

我想要一个带有--action= 标志的程序,其中有效的选择是dumpuploadupload 是默认值。如果(且仅当)dump 被选中,我希望还有一个 --dump-format= 选项。有没有办法使用 argparse 来表达这一点,还是我只需要接受所有参数并自己做逻辑。

【问题讨论】:

  • 执行--action=dump-csv--action=dump-some-other-format 之类的操作是否可行(从美学角度而言)?这将完全缓解“必需选项”的问题。
  • @dcrosta 它显然会起作用,但我不想那样做,我觉得它很笨拙。
  • 很公平,只是想确保您已经涵盖了明显的基础。
  • 他需要默认上传 -- parser.add_argument('--action', Choices=['upload', 'dump'], default='dump') 但我没有想到parser.error.

标签: python argparse


【解决方案1】:

argparse 模块提供了一种无需自己实现的方法 必要性检查。下面的示例使用“子解析器”或“子命令”。 我为“转储”实现了一个子解析器,为“格式”实现了一个。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('file', help='The file you want to act on.')
subparsers = parser.add_subparsers(dest='subcommand')
subparsers.required = True  # required since 3.7

#  subparser for dump
parser_dump = subparsers.add_parser('dump')
# add a required argument
parser_dump.add_argument(
    'format',
    choices=['csv', 'json'],
    help='Dump the file in this format.')

#  subparser for upload
parser_upload = subparsers.add_parser('upload')
# add a required argument
parser_upload.add_argument(
    'server',
    choices=['amazon', 'imgur'],
    help='Upload the file to this service.')

args = parser.parse_args()
print args
if args.subcommand == 'dump':
    print 'I will now dump "%s" in the %s format' % (args.file, args.format)
if args.subcommand == 'upload':
    print 'I will now upload "%s" to %s' % (args.file, args.server)

在命令行上看起来像这样:

$ python ap.py 
usage: ap.py [-h] file {upload,dump} ...
ap.py: error: too few arguments
$ python ap.py tmp.txt 
usage: ap.py [-h] file {upload,dump} ...
ap.py: error: too few arguments
$ python ap.py tmp.txt upload
usage: ap.py file upload [-h] {amazon,imgur}
ap.py file upload: error: too few arguments
$ python ap.py tmp.txt upload amazo
usage: ap.py file upload [-h] {amazon,imgur}
ap.py file upload: error: argument server: invalid choice: 'amazo' (choose from 'amazon', 'imgur')
$ python ap.py tmp.txt upload amazon
Namespace(file='tmp.txt', server='amazon', subcommand='upload')
I will now upload "tmp.txt" to amazon
$ python ap.py tmp.txt upload imgur
Namespace(file='tmp.txt', server='imgur', subcommand='upload')
I will now upload "tmp.txt" to imgur
$ python ap.py tmp.txt dump
usage: ap.py file dump [-h] {csv,json}
ap.py file dump: error: too few arguments
$ python ap.py tmp.txt dump csv
Namespace(file='tmp.txt', format='csv', subcommand='dump')
I will now dump "tmp.txt" in the csv format
$ python ap.py tmp.txt dump json
Namespace(file='tmp.txt', format='json', subcommand='dump')
I will now dump "tmp.txt" in the json format

更多信息: http://docs.python.org/dev/library/argparse.html#argparse.ArgumentParser.add_subparsers

【讨论】:

  • 命令行参数的设计与所要求的不同。
【解决方案2】:

解决问题的另一种方法是使用subcommands (a'la git) 和“action”作为第一个参数:

script dump --dump-format="foo"
script upload

【讨论】:

  • 一个限制是argparse 不允许多个subparsers
  • 这是错误的。您可以根据需要添加任意数量的子解析器。请参阅答案中引用的子命令链接。另请参阅Niels Bom's answer
  • ... 还是您的意思是 嵌套 子命令?像dump dumpsubcommand1dump subcommand2upload subcommand3 等...?
【解决方案3】:

你可以使用parser.error:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--action', choices=['upload', 'dump'], default='dump')
parser.add_argument('--dump-format')
args = parser.parse_args()
if args.action != 'dump' and args.dump_format:
    parser.error('--dump-format can only be set when --action=dump.')

【讨论】:

  • 这里只是描述报错的“argparse方式”。逻辑是手动实现的。不是有条件地要求参数的“argparse”方式。
  • 如果不是 "dump" 和 "format" 还有 5 个选项,它们都有自己的一组必需或非必需参数,这种检查必需性的方式可能会很快变得不清楚。
  • 此外,像 argparse.FileType 这样的东西会出现问题。对于不需要 FileType 参数时的某些选定操作,文件不存在会导致错误错误。
【解决方案4】:

这取决于您认为“自己做所有逻辑”的方式。您仍然可以使用 argparse 并按如下方式添加转储选项,而无需借助子命令:

from argparse import ArgumentParser
from sys import argv

parser = ArgumentParser()
action_choices = ['upload', 'dump']
parser.add_argument('--action', choices=action_choices, default=action_choices[1])
parser.add_argument('--dump-format', required=(action_choices[1] in argv))

这样,如果未选择转储操作,argparse 将不关心转储格式

【讨论】:

  • 这是针对特定用例的巧妙、优雅的解决方案
猜你喜欢
  • 2023-04-03
  • 2016-05-02
  • 2013-09-13
  • 2011-09-12
  • 2018-01-25
  • 1970-01-01
  • 2012-01-05
相关资源
最近更新 更多