23

I am using getopt to process a command line optional argument, which should accept a list. Something like this:

foo.py --my_list=[1, 2, 3, 4,5] 

But this trims everything after "[1,"

My questions are: A) Is there a way to specify a list without converting it into a string? (using getopt)

B) If I am to convert the list into a string, how to convert this list to a string? e.g. something like mylist.split("?") to get rid of square brackets ?? is there a better way?

Thank you

cppb
  • 2,319
  • 8
  • 32
  • 37

6 Answers6

29

There are two options that I can think of:

  • Use optparse, and use append action to specify what you want to do as: foo.py --my_list=1 --my_list=2 ....
  • Specify your commandline as foo.py --my_list='1,2,3,4,5', and then use x.split(',') to get your values in a list. You can use getopt or optparse for this method.

The advantage of the first method is that you can get integer values in the list directly, at the expense of the commandline being longer (but you can add a single-charecter option for --my_list if you want). The advantage of the second is shorter command line, but after the split(), you need to convert the string values '1', '2', etc., to integers (pretty easy as well).

Alok Singhal
  • 93,253
  • 21
  • 125
  • 158
  • 4
    as this post is 5 years old, `optparse` is now deprecated for `argparse` – SAAD Sep 04 '15 at 13:06
  • What do you mean by 'use append action'? It sounds exciting but not sure what you are talking about. – Monica Heddneck Jun 03 '17 at 02:06
  • @MonicaHeddneck See https://docs.python.org/3/library/optparse.html#standard-option-actions - they have an example of the "append" action: `parser.add_option("-t", "--tracks", action="append", type="int")`. – Alok Singhal Jun 03 '17 at 04:28
  • Please take a loot at my answer, as this one is older and not the preferable way to do this. – Nick Jul 19 '19 at 19:13
14

If I can't use a standard parser (optparse or argparse) to my application then I use the ast.literal_eval function to parse input arguments of type list as follows:

import sys, ast

inputList = ast.literal_eval( sys.argv[1] )
print type( inputList )
print inputList

Let suppose that this code is stored in testParser.py file. By executing the script:

$ python testParser.py  "[1,2,3,4, [123, 456, 789], 'asdasd']"

we get the following output:

<type 'list'>
[1, 2, 3, 4, [123, 456, 789], 'asdasd']

So, using the secure enough ast.literal_eval function and inserting the list as a string of code we have the desirable result.

Useful links:

Using python's eval() vs. ast.literal_eval()?

http://docs.python.org/2/library/functions.html?highlight=eval#eval

Community
  • 1
  • 1
funk
  • 2,221
  • 1
  • 24
  • 23
7

Maybe you should just enclose the argument in quotes?

foo.py "--my_list=[1, 2, 3, 4,5]"

Otherwise every space will be treated as a separator for arguments.

Joey
  • 344,408
  • 85
  • 689
  • 683
  • 3
    And that's not because of python but due to the shell which parses the arguments and provides them to the python program. – extraneon Jan 18 '10 at 14:29
  • 1
    Partly true. On Windows the command line is just a string. And even UNIX does not have any special data structure that passes arguments to the program, it's still only a string. However, it's a widely implemented convention, but not universal. And yes, the C runtime has specifications for that. – Joey Jan 18 '10 at 14:33
  • 1
    You can also do `--my-list="[1, 2, 3, 4,5]"`. I usually use this form because it's usually something like `--my-list="$MY_LIST"`. – Mike DeSimone Jan 18 '10 at 14:43
  • Ah, I thought so much already but wasn't familiar enough with getopt to know whether that would work. – Joey Jan 18 '10 at 14:45
6

An updated way is to use the argparse library and add the list as a command line argument. This way, you don't have to do any manual parsing.

Example:

parser = argparse.ArgumentParser()
parser.add_argument(
        "-values",
        nargs="*",  # expects ≥ 0 arguments
        type=int,
        default=[35, 40, 50, 60, 70, 80, 90],  # default list if no arg value
    )

Which you would then call like this:

python3 someprogram.py -values 1 2 3
Nick
  • 823
  • 2
  • 10
  • 22
1

From the python optparse help page: "

parser.add_option("-f")
parser.add_option("-p", type="float", nargs=3, dest="point")

As it parses the command line

-f foo.txt -p 1 -3.5 4 -fbar.txt

optparse will set

options.f = "foo.txt"
options.point = (1.0, -3.5, 4.0)
options.f = "bar.txt"

"

highvelcty
  • 665
  • 5
  • 2
0

I have been redirected from the dup question:
How to pass an array to python through command line - Stack Overflow

I’m answering that question:
The arguments on the command line are strings, they're not parsed like literals in the program.
argv construct the strings automatically to a list from command line arguments (as separated by spaces), in short, sys.argv is a list.

    from sys import argv
    cmd = "arr = {sys.argv[1]}".format(argv)
    exec(cmd)
    print(arr[2])
AbstProcDo
  • 19,953
  • 19
  • 81
  • 138