I was trying to pass two lists containing integers as arguments to a python code. But sys.argv[i] gets the parameters as a list of string.

Input would look like,

$ python filename.py [2,3,4,5] [1,2,3,4] 

I found the following hack to convert the list.

strA = sys.argv[1].replace('[', ' ').replace(']', ' ').replace(',', ' ').split() strB = sys.argv[2].replace('[', ' ').replace(']', ' ').replace(',', ' ').split() A = [float(i) for i in strA] B = [float (i) for i in strB] 

Is there a better way to do this?

2

8 Answers

Don't reinvent the wheel. Use the argparse module, be explicit and pass in actual lists of parameters

import argparse # defined command line options # this also generates --help and error handling CLI=argparse.ArgumentParser() CLI.add_argument( "--lista", # name on the CLI - drop the `--` for positional/required parameters nargs="*", # 0 or more values expected => creates a list type=int, default=[1, 2, 3], # default if nothing is provided ) CLI.add_argument( "--listb", nargs="*", type=float, # any type/callable can be used here default=[], ) # parse the command line args = CLI.parse_args() # access CLI options print("lista: %r" % args.lista) print("listb: %r" % args.listb) 

You can then call it using

$ python my_app.py --listb 5 6 7 8 --lista 1 2 3 4 lista: [1, 2, 3, 4] listb: [5.0, 6.0, 7.0, 8.0] 
3

Command line arguments are always passed as strings. You will need to parse them into your required data type yourself.

>>> input = "[2,3,4,5]" >>> map(float, input.strip('[]').split(',')) [2.0, 3.0, 4.0, 5.0] >>> A = map(float, input.strip('[]').split(',')) >>> print(A, type(A)) ([2.0, 3.0, 4.0, 5.0], <type 'list'>) 

There are libraries like argparse and click that let you define your own argument type conversion but argparse treats "[2,3,4]" the same as [ 2 , 3 , 4 ] so I doubt it will be useful.

edit Jan 2019 This answer seems to get a bit of action still so I'll add another option taken directly from the argparse docs.

You can use action=append to allow repeated arguments to be collected into a single list.

>>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', action='append') >>> parser.parse_args('--foo 1 --foo 2'.split()) Namespace(foo=['1', '2']) 

In this case you would pass --foo ? once for each list item. Using OPs example: python filename.py --foo 2 --foo 3 --foo 4 --foo 5 would result in foo=[2,3,4,5]

4

I tested this on my end, and my input looks like this:

python foo.py "[1,2,3,4]" "[5,6,7,8,9]" 

I'm doing the following to convert the two params of interest:

import ast import sys list1 = ast.literal_eval(sys.argv[1]) list2 = ast.literal_eval(sys.argv[2]) 
1

Why not:

python foo.py 1,2,3,4 5,6,7,8 

Much cleaner than trying to eval python and doesn't require your user to know python format.

import sys list1 = sys.argv[1].split(',') list2 = [int(c) for c in sys.argv[2].split(',')] # if you want ints 

You can also do the following:

say, you have foo.py :

import json import sys data = json.loads(sys.argv[1]) print data, type(data) 

Then if you run the above as : python foo.py "[1,2,3]"

Output:

[1, 2, 3] <type 'list'>

2

No, there is no way pass a list in a command line argument. Command line arguments are always string. But there is a better way to convert it to list. You can do it like that:

import ast A = ast.literal_eval(strA) B = ast.literal_eval(strB) 

You can simply use nargs='+' option of argparse

import argparse parser = argparse.ArgumentParser() parser.add_argument('--myarg', dest='myarg', required=False, help='--myarg 100 100 100 takes a list of 3 elements, each is of value 100 ', nargs='+', type=int, default=[100,100,100]) 

You can then pass arguments like this:

python your_file.py --myarg 1 2 3 

This will be stored in your program in myarg as [1,2,3]

print(myarg) 

Outputs:

[1,2,3] 

You have to escape:

python some.py \[2,3,4,5\] \[1,2,3,4\] 

some.py

import sys print sys.argv[1] print sys.argv[2] 

this gives me:

[2,3,4,5] [1,2,3,4] 

Bash out

UPDATE:

import sys import ast d = ast.literal_eval(sys.argv[1]) b = ast.literal_eval(sys.argv[2]) for a in d: print a for e in b: print e 

first will give:

2 3 4 5 

and second will give

1 2 3 4 
3

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy