【问题标题】:Python Argparse - conditionally required arguments based on the value of another argumentPython Argparse - 基于另一个参数的值有条件地需要参数
【发布时间】:2019-02-04 18:43:33
【问题描述】:

我正在尝试编写一个可以在命令行中控制的守护程序服务。比如启动服务

python3 test.py -c start -d /mydownloadfolder/ -j /myconfig.json

停止服务,

python3 test.py -c stop

-d-j参数只有在我启动服务时才需要。因此,我需要根据另一个参数的值来实现有条件需要的参数。

我做了一些搜索,发现这篇有用的帖子Python Argparse conditionally required arguments 不同之处在于:我需要检查“--command”的值,而不是检查“--command”的存在。

这是我的暂定解决方案:

PARSER.add_argument('-c', '--command', required=True, help='provide a valid command: start, stop, restart, or status')
NEED_MORE_ARGS = PARSER.parse_args().command.lower().startswith('start')
PARSER.add_argument('-d', '--download', required=NEED_MORE_ARGS , default=LOCAL_DOWNLOAD, help='set account download folder')
PARSER.add_argument('-j', '--input',  required=NEED_MORE_ARGS, default=JSON_INPUT, help='set input json file')

我解析了中间的args得到NEED_MORE_ARGS(boolean),然后添加其他的args。代码似乎不干净。有没有更好的方法来做到这一点?

==============

更新:暂定解决方案不起作用。 :(

【问题讨论】:

  • 我认为该链接很好地涵盖了选项。 argparse 中没有内置任何东西可以进行这种交叉检查。我更喜欢解析后测试选项。但也要考虑一下——你想提供什么样的help
  • 我可能会补充一点,如果您不需要'-c' 标志,您可以使用子解析器机制。 'stop' 可以是一个不带任何附加参数的子解析器,'start' 一个带有 2 个必需参数的子解析器。
  • 在您提到的链接中,最佳答案是关于查看 sys.argv。这对我来说很有意义。首先忘记 argparse,只需检查 -c 并在 argv 中停止或启动。然后根据您在 sys.argv 中找到的内容使用 argparse。或者干脆忘记 argparse 并自己处理 sys.argv。对我来说似乎更简单。

标签: python argparse


【解决方案1】:

我认为您可以使用两个解析器来做到这一点:

import argparse

if __name__ == '__main__':
    command_parser = argparse.ArgumentParser()
    command_parser.add_argument('-c', '--command', required=True,
                                help='provide a valid command: start, stop, restart, or status')

    if command_parser.parse_known_args()[0].command.lower().startswith('start'):
        option_parser = argparse.ArgumentParser()
        option_parser.add_argument('-d', '--download', required=True, help='set account download folder')
        option_parser.add_argument('-j', '--input', required=True, help='set input json file')
        option_parser.parse_known_args()

或者您可以使用子解析器,在您的情况下这可能会更好:

import argparse

if __name__ == '__main__':
    command_parser = argparse.ArgumentParser()

    subparsers = command_parser.add_subparsers(help='Choose a command')

    start_parser = subparsers.add_parser('start', help='"start" help')
    start_parser.add_argument('-d', '--download', required=True, help='set account download folder')
    start_parser.add_argument('-j', '--input', required=True, help='set input json file')
    start_parser.set_defaults(action=lambda: 'start')

    stop_parser = subparsers.add_parser('stop', help='"stop" help')
    stop_parser.set_defaults(action=lambda: 'stop')

    command_parser.parse_args()

在这种情况下,命令行语法会有所不同:

python3 test.py start -d /mydownloadfolder/ -j /myconfig.json

python3 test.py stop

【讨论】:

  • 感谢您的建议
猜你喜欢
  • 2020-11-05
  • 2014-10-26
  • 2011-10-07
  • 2015-09-13
  • 2020-03-23
  • 1970-01-01
  • 2018-08-28
  • 2018-01-22
  • 1970-01-01
相关资源
最近更新 更多