-2

I have written a python script to get inputs from user but user input is getting splitted with ",". I dont want user input to get modified.

#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-f","--file_name", type=str)
parser.add_argument("-i", "--ingress",type=list)
args = parser.parse_args()
print args.file_name
print args.ingress
print(type(args.ingress))

Output:

./input_parse.py -f output.txt -i [["1,2,3,4"],80,90,"tcp"]
output.txt
['[', '[', '1', ',', '2', ',', '3', ',', '4', ']', ',', '8', '0', ',', '9', '0', ',', 't', 'c', 'p', ']']
<type 'list'>

Expected Output:

output.txt
[["1,2,3,4"],80,90,"tcp"]
<type 'list'>

Later I need to iterate over the list and take list[0], list[1] and so on.

user60679
  • 709
  • 14
  • 28
  • 3
    Change the type back to `str`. `type=list` makes Python call `list()` on the loaded string, and `list('foo')` returns a list of all characters. – poke Aug 24 '17 at 08:36
  • No It's not working! – user60679 Aug 24 '17 at 08:48
  • type=list does the same thing as list('foo') @poke – user60679 Aug 24 '17 at 08:49
  • That’s what I said. Read my comment again. – poke Aug 24 '17 at 08:50
  • ```>>> name = "Suresh" >>> print(list(name)) ['S', 'u', 'r', 'e', 's', 'h']``` – user60679 Aug 24 '17 at 08:51
  • @poke Please look at the expected output and then downvote my question! – user60679 Aug 24 '17 at 08:53
  • change this line `parser.add_argument("-i", "--ingress",type=list)`, here you defined `type=list` make it `type=str`. – Bijoy Aug 24 '17 at 08:58
  • @Bijoy I need to iterate over the list – user60679 Aug 24 '17 at 09:00
  • You can convert it to list by using `eval(string)`, but only if the value is from trusted source – Bijoy Aug 24 '17 at 09:01
  • Possible duplicates: [argparse option for passing a list as option](https://stackoverflow.com/questions/15753701/argparse-option-for-passing-a-list-as-option), [python argh/argparse: How can I pass a list as a command-line argument?](https://stackoverflow.com/questions/9398065/python-argh-argparse-how-can-i-pass-a-list-as-a-command-line-argument) – poke Aug 24 '17 at 09:02

1 Answers1

1

The argument parser, takes everything as a string then applies the type you specified on the input. If you really need to pass a list, just convert back to a str and convert it to a list with a helper function:

Option 1:

you could do something like this:

#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-f","--file_name", type=str)
parser.add_argument("-i", "--ingress",type=str)
args = parser.parse_args()
print args.file_name
print args.ingress
print(type(args.ingress))

def helper(x):
        l = x.split('|')
        ll = [[l[0]]]+l[1].split(',')
        ll[1], ll[2] = int(ll[1]), int(ll[2])
        return ll

args.ingress = helper(args.ingress)
print args.ingress 
print type(args.ingress)

And then pass the argument like this:

python /tmp/test.py -f output.txt -i "1,2,3,4|80,90,tcp"

The output will look as you expect it:

output.txt
1,2,3,4|80,90,tcp
<type 'str'>
[['1,2,3,4'], 80, 90, 'tcp']
<type 'list'>

Option 2:

This can also be changed to take a list:

#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-f","--file_name", type=str)
parser.add_argument("-i", "--ingress",type=str)
args = parser.parse_args()
print args.file_name
print args.ingress
print(type(args.ingress))

def helper(x):
        l = x.split(']')
        l[0] = l[0].replace('[[','')
        l = l[:2]
        ll = [[l[0]]]+l[1].split(',')[1:]
        ll[1], ll[2] = int(ll[1]), int(ll[2])
        return ll

args.ingress = helper(args.ingress)
print args.ingress 
print type(args.ingress)

You call it like this:

python /tmp/test.py -f output.txt -i [["1,2,3,4"],80,90,"tcp"]

output:

output.txt
[[1,2,3,4],80,90,tcp]
<type 'str'>
[['1,2,3,4'], 80, 90, 'tcp']
<type 'list'>

Option 3:

Use ast.literal_eval (which is dangerous than eval, as anyone can inject code into your program and potentially harm your system):

#!/usr/bin/python
import ast
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-f","--file_name", type=str)
parser.add_argument("-i", "--ingress",type=str)
args = parser.parse_args()
print args.file_name
print args.ingress
print(type(args.ingress))

args.ingress = ast.literal_eval(args.ingress)
print args.ingress
print type(args.ingress)

call:

python /tmp/test.py -f output.txt -i '[["1,2,3,4"],80,90,"tcp"]'

output:

output.txt
[["1,2,3,4"],80,90,"tcp"]
<type 'str'>
[['1,2,3,4'], 80, 90, 'tcp']
<type 'list'>
Mohamed Ali JAMAOUI
  • 14,275
  • 14
  • 73
  • 117
  • If you replace `eval` with `ast.literal_eval` it becomes non-dangerous and (in my opinion) the best solution. – SethMMorton Aug 16 '18 at 15:48
  • Why mention `eval` at all? Or, at least the grammar should be updated because as written it sounds like `literal_eval` is as dangerous as `eval`. – SethMMorton Aug 16 '18 at 23:49