23

I am trying to pass an array to the python

import sys
arr = sys.argv[1]
print(arr[2])

My command is

python3 test.py [1,2,3,4,5] 0

I hope the result it

2

However, it is

,
alexis
  • 48,685
  • 16
  • 101
  • 161
Luyao Wang
  • 269
  • 1
  • 3
  • 11
  • another similar answer http://stackoverflow.com/questions/7605631/passing-a-list-to-python-from-command-line – mgilbert Apr 28 '16 at 21:56
  • `[1,2,3,4,5]` is a filename globbing pattern. It matches any filename whose name is a single character that's either 1 through 5 or a comma. – Barmar Apr 28 '16 at 21:56
  • If you want to use it as a literal argument to the script, you need to put it in quotes. – Barmar Apr 28 '16 at 21:57

2 Answers2

46

The elements of argv are strings, they're not parsed like literals in the program.

You should just pass a comma-separated string (without the brackets):

python3 test.py 1,2,3,4,5 0

and then use split() to convert it to an array.

import sys
arr = sys.argv[1].split(',')
print(arr[2])
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 1
    Great answer. Just wanted to add that, in case you want to use the list as an array, you can convert it like: arr = sys.argv[1].split(',') ; arr = np.array([float(i) for i in arr]) – Carl Jul 19 '20 at 18:49
  • What if I would like to pass a 2d array containing all kinds of string including commas? I've tried defining it as a r"""[["","",""]["","","",]]""" but my first element still is just up to the first comma. Is there no way to pass the entire array as a single string? – Johnson Dec 05 '22 at 13:04
  • @Johnson If you want to use Python syntax in the argument, you can use `ast.literal_eval()` to parse it. You'll also need to put it in quotes to prevent the shell from parsing all the brackets and quotes. – Barmar Dec 06 '22 at 02:04
  • @Barmar Thans for your suggestion, but it doesn't work for me. I tried ast.literal_eval(sys.argv) but it just turns the entire arguments array into a string, like this: '['path/main.py', '[[1, 000, Some, 'data'],[ 'my', 'array']]'] with the quotes appearing in random places. my argument is """[["Some data", "in my array"], ["That's not broken", "like what ast.literal_eval() returns"]]""" – Johnson Dec 07 '22 at 15:39
  • @Johnson Please ask a new question, showing exactly what you're typing in the CLI, and what you tried in the code. – Barmar Dec 07 '22 at 20:27
  • @Barmar Sure thing: [How do I pass an array of strings to a python script as an argument?](https://stackoverflow.com/questions/74727714/how-do-i-pass-an-array-of-strings-to-a-python-script-as-an-argument) – Johnson Dec 08 '22 at 08:57
12

Commandline arguments are strings. Even integers have to be converted from string to int. If you use the list syntax you show in your example, you'll need to run the argument through some sort of parser (your own parser, something from ast, or eval-- but don't use eval). But there's a simpler way: Just write the arguments separately, and use a slice of sys.argv as your list. Space-separated arguments is the standard way to pass multiple arguments to a commandline program (e.g., multiple filenames to less, rm, etc.).

python3 test.py -n a b c 1 2 3

First you'd identify and skip arguments that have a different purpose (-n in the above example), then simply keep the rest:

arr = sys.argv[2:]
print(arr[3])   # Prints "1"

PS. You also need to protect any argument from the shell, by quoting any characters with special meaning(*, ;, spaces that are part of an argument, etc.). But that's a separate issue.

alexis
  • 48,685
  • 16
  • 101
  • 161