Python Argparse - conditionally required arguments based on the value of another argument

大城市里の小女人 提交于 2021-01-28 03:35:41

问题


I am trying to write a daemon service, which can be controlled in the command line. For example, to start the service

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

to stop the service,

python3 test.py -c stop

The -d -j parameters are required only when I start the service. Therefore, I need to implement conditionally required arguments based on the value of another argument.

I did some search and found this useful post Python Argparse conditionally required arguments The difference is: instead of checking the existence of '--command', I need to check the value of the '--command'.

Here is my tentative solution:

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

I parsed the args in the middle to get NEED_MORE_ARGS(boolean), and then add other args. The code seems not clean. Is there a better way to do this?

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

Updated: The tentative solution does not work. :(


回答1:


I think you can use two parsers to do that:

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

or you can use a subparser, which is probably better in your case:

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

in this case command line syntax will be bit different:

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

python3 test.py stop


来源:https://stackoverflow.com/questions/52086550/python-argparse-conditionally-required-arguments-based-on-the-value-of-another

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!