how to perform automatic type conversion in dynamic argument parsing

无人久伴 提交于 2020-12-15 05:34:29

问题


Most of my python codes I send a (sometimes long!) list of arguments to, which I know how to parse using getopt. All well and good so far...

However I find it tiresome to type out a long if-then-else structure to pass all the arguments to a list of variables (usually of the same name as the passed argument), so I wanted to write a function that simply dynamically accepts arguments and places them in dynamical variable names, which seemed easiest to do using a dictionary, so that the pre-defined dictionary provided the default possible option list as well as default argument values.

I did this in the following way:

import getopt, sys

def get_args(runpars):
    """routine to dynamically accept arguments"""
    try:
        opts, args = getopt.getopt(sys.argv[1:],"h",[key+"=" for key in runpars])
    except getopt.GetoptError:
        print ('Use these arguments ',runpars)
        sys.exit(2)
    for opt, arg in opts:
        runpars[opt[2:]]=arg

    return(runpars)

if __name__ == "__main__":
    # default argument values:
    runpars={"a":1,"animal":"cat","f":3.3}
    runpars=get_args(runpars)
    print(runpars)

This essentially works:

If I pass an argument not in the dictionary, it bombs as intended with the key list:

getopts_test.py --a=4000 --animal="dog" --c=2.1 --dfrfrfr=23
Use these arguments  {'a': 1, 'animal': 'cat', 'f': 3.3}

If I pass some arguments it correctly overrides my options as desired

getopts_test.py --a=4000 --animal="dog" 
{'a': '4000', 'animal': 'dog', 'f': 3.3}

BUT! as arguments are all passed as strings, my type has now changed to a string... In my old fashioned clunky if-then-else manually parsing, I of course would convert each argument manually with e.g.

param=int(arg) 

etc etc, but now I can't do this. So my questions is, is there a way somehow of testing the original dictionary key type and using that to convert the argument from a string.

I essentially want to find some "as_type" method, like

runpars[opt[2:]]=arg.as_type(original key this opt matched)

回答1:


You found a really neat way of solving this using argparse. You can take advantage of the Namespace object which can be passed to the parse_args() method to better handle the defaults. The idea is simple: instead of creating a new namespace object from the passed arguments and then augmenting it with the defaults, simply pre-create a namespace object from the defaults, and have argparse update it with the passed arguments.

This will reduce your code a bit:

def get_args(defaultpars):
    parser = argparse.ArgumentParser(description='Dynamic arguments')
    namespace = argparse.Namespace(**defaultpars)

    # add each key of the default dictionary as an argument expecting the same type 
    for key, val in defaultpars.items():
        parser.add_argument('--'+key, type=type(val))
    
    parser.parse_args(namespace=namespace)

    return vars(namespace)



回答2:


Thanks to @Wolfgang Kuehn for his pointer to argparse. That has the useful "type" option in add_argument, which solved my problem!

So here is my new solution written from scratch using argparse:

import argparse

def get_args(defaultpars):
    parser = argparse.ArgumentParser(description='Dynamic arguments')

    # add each key of the default dictionary as an argument expecting the same type 
    for key,val in defaultpars.items():
        parser.add_argument('--'+key,type=type(val))
    newpars=vars(parser.parse_args())

    # Missing arguments=None need to be overwritten with default value
    for key,val in newpars.items():
        if val==None:
            newpars[key]=defaultpars[key]
    return(newpars)

if __name__ == "__main__":

    # default values:
    runpars={"a":1,"animal":"cat","f":3.3}
    runpars=get_args(runpars)
    print(runpars)

giving the correct types in the resulting dictionary:

getopts_test.py --a=4000 --animal="dog" 
{'a':4000, 'animal': 'dog', 'f': 3.3}


来源:https://stackoverflow.com/questions/64367210/how-to-perform-automatic-type-conversion-in-dynamic-argument-parsing

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