Argparse: Check if any arguments have been passed

爷,独闯天下 提交于 2019-12-18 10:14:04

问题


My script should start a demo mode, when the no parameters are given. I tried this:

args = parser.parse_args()
if len(args) == 0:
    run_demo()
else:
    # evaluate args

Which gives a *** TypeError: object of type 'Namespace' has no len() as args is no list.

How would I achieve what I want?


回答1:


If your goal is to detect when no argument has been given to the command, then doing this via argparse is the wrong approach (as Ben has nicely pointed out).

Think simple! :-) I believe that argparse does not depopulate sys.argv. So, if not len(sys.argv) > 1, then no argument has been provided by the user.




回答2:


argparse lets you set (inside a Namespace object) all the variables mentioned in the arguments you added to the parser, based on your specification and the command line being parsed. If you set a default, then those variables will have that default value if they weren't seen on the command line, they won't be absent from the Namespace object. And if you don't specify a default, then there is an implicit default of None. So checking the length of the Namespace object, however you manage to do it, doesn't make sense as a way to check whether any arguments were parsed; it should always have the same length.

Instead, if you know you've got a bunch of arguments with no defaults and you want to check whether any of them were set to any non-None value... do that. You can use a list comprehension and the vars function to loop over them without having to duplicate the list of names from the add_argument calls, as shown in Martijn's answer.

It gets a little trickier if some of your arguments have default values, and more so if they have default values that could be explicitly provided on the command line (e.g. a numeric argument that defaults to 0 makes it impossible to tell the default from the user providing 0). In that case I'm not sure that there's a general solution that always works without knowledge of what the arguments are.




回答3:


If one really needs the argument number (for whatever reason). I have found this code very helpful (but do not know how much optimised it is, and I'd appreciate any comment on it).

args = parser.parse_args()
print( len( vars(args) ) )

This version counts only the -xx parameters and not any additional value passed.

If one wants everything (also the values passed), then just use len(sys.argv) as previously mentioned.




回答4:


Don't use argparse. Instead just use sys.argv. argparse creates a Namespace, so it will always give you a "dict" with their values, depending on what arguments you used when you called the script.

Here's what I've done in the past:

args = parser.parse_args()
if len(sys.argv) == 1:
    parser.print_help()
    sys.exit()
return args



回答5:


Let us assume the following example to extend Yours for completeness:

#!/usr/bin/env python3

import argparse

...
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('input', nargs='?' action='store')
    parser.add_argument('-l', '--length', type=int, action='store')
    parser.add_argument('-v', '--verbose', action='store_true')
    args = parser.parse_args()
    if (args.input == None and args.length == None):
        parser.print_help()
    else:
        print(args)

if __name__ == '__main__':
    main()

Your Namespace object, mentioned by @Ben, in this example is args. From the strings in parser.add_argument a variable is created. You can access it through args.input or args.length or args.verbose. You can verify this by executing print(args) which will actually show something like this:

Namespace(input=None, length=None, verbose=False)

since verbose is set to True, if present and input and length are just variables, which don't have to be instantiated (no arguments provided).

Also helpful can be group = parser.add_mutually_exclusive_group() if you want to ensure, two attributes cannot be provided simultaneously.

For further reference, please refer to:

  • https://docs.python.org/3/howto/argparse.html Well structured HOWTO
  • https://docs.python.org/3/library/argparse.html Argparse module documentation



回答6:


I expanded 2dvisio's concept to count non zero or None arguments:

vm_opts = parser.parse_args()
v = vars(vm_opts)
n_args = sum([ 1 for a in v.values( ) if a])



回答7:


I know it's an old thread but I found a more direct solution that might be useful for others as well:

You can check if any arguments have been passed:

if any(vars(args).values()):
    # evaluate args

Or, if no arguments have been passed(note the not operator):

if not any(vars(args).values()):
    run_demo()

Explanation:

  • parse_args() returns a "Namespace" object containing every argument name and their associated value. Example: Namespace(arg1='myfile.txt', arg2='some/path/to/some/folder')

  • If no arguments have been passed, parse_args() will return the same object but with all the values as None. Example: Namespace(arg1=None, arg2=None)

This object is not iterable, though, so you have to use vars() to turn it into a dict so we can access the values.

Finally, as we now have a dict on hands, we can get all the values(in a list), with .values(), and use the built-in any() function to check if any of the values is not None. To make it clearer: any() returns False if there isn't a single value that is not None, False or 0(check the docs for reference) in the list you've fed to it.

Hope it helps.



来源:https://stackoverflow.com/questions/10698468/argparse-check-if-any-arguments-have-been-passed

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