简体   繁体   中英

python argparse: how to use other parsed argument as parameter at calling function in type keyword?

I am trying to create an user interface using argparse module.

One of the argument need to be converted, so I use the type keyword:

add_argument('positional', ..., type=myfunction)

and there is another optional argument:

add_argument('-s', dest='switch', ...) 

in addition, I have

parsed_argument=parse_args()

However, in myfunction , I hope I can use an additional parameter to control the behavior, which is the optional argument above, ie

def myfunction(positional, switch=parsed_argument.switch): 
     ...

How can I achieve that?

Simple answer: You can't. The arguments are parsed separately, and there is no real guarantee that some order is maintained. Instead of putting your logic into the argument type, just store it as a string and do your stuff after parsing the command line:

parser.add_argument('positional')
parser.add_argument('-s', '--switch')

args = parser.parse_args()

myfunction(args.positional, switch=args.switch)

I'm not sure I did understand correctly what you want to achieve, but if what you want to do is something that looks like:

myprog.py cmd1 --switcha
myprog.py cmd2 --switchb

yes you can, you need to use subparsers. I wrote a good example of it for a little PoC I wrote to access stackoverflow's API from CLI . The whole logic is a bit long to put thoroughly here, but mainly the idea is:

  1. create your parser using parser = argparse.ArgumentParser(...)
  2. create the subparsers using subparsers = parser.add_subparsers(...)
  3. add the commands with things like `subparser.add_parser('mycommand', help='Its only a command').set_defaults(func=mycmd_fn) where
  4. mycmd_fn takes args as parameters where you have all the switches you issued to the command!

the difference from what you ask, is that you'll need one function per command, and not one function with the positional argument as first argument. But you can leverage that easily by having mycmd_fn being like: mycmd_fn = lambda *args: myfunction('mycmd', *args)

HTH

From the documentation:

type= can take any callable that takes a single string argument and returns the converted value:

Python functions like int and float are good examples of a type function should be like. int takes a string and returns a number. If it can't convert the string it raises a ValueError . Your function could do the same. argparse.ArgumentTypeError is another option. argparse isn't going to pass any optional arguments to it. Look at the code for argparse.FileType to see a more elaborate example of a custom type .

action is another place where you can customize behavior. The documentation has an example of a custom Action. Its arguments include the namespace , the object where the parser is collecting the values it will return to you. This object contains any arguments have already been set. In theory your switch value will be available there - if it occurs first.

There are many SO answers that give custom Actions .

Subparsers are another good way of customizing the handling of arguments.

Often it is better to check for the interaction of arguments after parse_args . In your case 'switch' could occur after the positional and still have effect. And argparse.Error lets you use the argparse error mechanism (eg displaying the usage)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM