简体   繁体   中英

Passing a tuple as command line argument

My requirement is to pass a tuple as command line argument like

--data (1,2,3,4)

I tried to use the argparse module, but if I pass like this it is receiving as the string '(1,2,3,4)' . I tried by giving type=tuple for argparse.add_argument , but is of no use here.

Do I have to add a new type class and pass that to type argument of add_argument ?

Update

I tried the ast.literal_eval based on answers. Thanks for that. But it is giving spaces in the result as shown below.

(1,2,3,4)
<type 'str'>
(1, 2, 3, 4)
<type 'tuple'>

Set nargs of the data argument to nargs="+" (meaning one or more) and type to int , you can then set the arguments like this on the command line:

--data 1 2 3 4

args.data will now be a list of [1, 2, 3, 4] .

If you must have a tuple, you can do:

my_tuple = tuple(args.data)

Putting it all together:

parser = argparse.ArgumentParser()
parser.add_argument('--data', nargs='+', type=int)
args = parser.parse_args()
my_tuple = tuple(args.data)

I had same requirement. Could not find in standard packages. So, rolled this. Python 3x. Put inside simple argv parser, called one arg at a time:

  • var is passed in default, of correct type.
  • argval is found command line string. Comma separated,no spaces. ie 1,2,3 or one,two,three.

Works with bash shell, may need quotes, other adjustments for other shells, OS's. Same technique works non list types. This version creates a homogeneous list or tuple, based on var[0].

example:

./foo.py   --mytuple 1,2,3,4,5

code:

def chk_arg( var, argstr, dbg=False): 
    ### loop on sys.argv here .....
    # if list/tuple type, use list comprehension
    # converts csv list to list or tuple 'type(var)' of 'type(var[0])' items. 
    if type(var) is list or type(var) is tuple:  
        val = type(var)([type(var[0])(i) for i in argval.split(',')]) 

If you want to scale this, not deal with syntax trees, and provide the tuple conversion within the argument, you'll need a custom argparse type. (I needed this since my parser is in a package, and I didn't want to require my users to all write my_tuple = tuple(args.data) . With an argument type, you can also receive a string with parenthesis like the original question. Also, I wouldn't include nargs , because that will wrap your custom type output into a list, which basically defeats the purpose of your custom type. I mapped a float because my input was something like "0.9, 0.99", but your int works the same:

def tuple_type(strings):
    strings = strings.replace("(", "").replace(")", "")
    mapped_int = map(int, strings.split(","))
    return tuple(mapped_int)

parser = argparse.ArgumentParser()
parser.add_argument('--data', type=tuple_type)
args = parser.parse_args()

This way you can send in --data "(1,2,3,4)" or --data "1,2,3,4"

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