0

I wrote a function in python which takes 2 lists (with the same length) and returns another list with 2 elements. the function works perfectly but I am trying to run the python script in command line. to do so, I want to use argparse module in python. I wrote the following script in python3 using the following command:

python3 text.py a b results

the script should take 3 arguments 2 lists as input and one list as output. here is the script:

def fun(a, b):
    a_is_greater = 0
    b_is_greater = 0
    for element_a, element_b in zip(a, b):
        if element_a > element_b:
            a_is_greater += 1
        elif element_a < element_b:
            b_is_greater += 1
    return [a_is_greater, b_is_greater]


def main():
    import argparse
    ap = argparse.ArgumentParser(description="")
    ap.add_argument('--list-type', type=list)
    ap.add_argument('--list-type', type=list)
    ap.add_argument('-o', '--outlist', required=True)

    args = ap.parse_args()

    results = fun(a, b)
    return results

if __name__ == "__main__":
    from signal import signal, SIGPIPE, SIG_DFL
    signal(SIGPIPE, SIG_DFL)

    try:
        main()
    except IOError as e:
        if e.errno != 32:
            raise
    except KeyboardInterrupt as e:
        pass

do you know how to fix it? I have tried these 2 lists: a = [4, 5, 2] and b = [3, 5, 4]. fun function in the script works perfectly for these 2 inputs.

2 Answers 2

1

Is this better?

python3 text.py --list1 [4,5,2] --list2 [3,5,4] -o result # [1, 1]

def main():
    import argparse

    ap = argparse.ArgumentParser(description="")
    ap.add_argument('--list1', type=list)
    ap.add_argument('--list2', type=list)
    ap.add_argument('-o', '--outlist', required=True)
    args = ap.parse_args()

    results = fun(args.list1, args.list2)
    print(results)
    return results

Code :

def fun(a, b):
    a_is_greater = 0
    b_is_greater = 0
    for element_a, element_b in zip(a, b):
        if element_a > element_b:
            a_is_greater += 1
        elif element_a < element_b:
            b_is_greater += 1
    return [a_is_greater, b_is_greater]


def main():
    import argparse

    ap = argparse.ArgumentParser(description="")
    ap.add_argument('--list1', type=list)
    ap.add_argument('--list2', type=list)
    ap.add_argument('-o', '--outlist', required=True)
    args = ap.parse_args()

    results = fun(args.list1, args.list2)
    print(results)
    return results

if __name__ == "__main__":
    from signal import signal, SIGPIPE, SIG_DFL
    signal(SIGPIPE, SIG_DFL)

    try:
        main()
    except IOError as e:
        if e.errno != 32:
            raise
    except KeyboardInterrupt as e:
        pass
Sign up to request clarification or add additional context in comments.

Comments

0

With the corrected code using type=list, sys.argv and args display as:

1353:~/mypy$ python3 stack56531390.py --list1 [4,5,2] --list2 [3,5,4] -o result
['stack56531390.py', '--list1', '[4,5,2]', '--list2', '[3,5,4]', '-o', 'result']
Namespace(list1=['[', '4', ',', '5', ',', '2', ']'], list2=['[', '3', ',', '5', ',', '4', ']'], outlist='result')
[1, 1]

Note that the 'lists' come in as strings. The list function splits that string into a list of characters.

In [607]: list('astring')                                                                              
Out[607]: ['a', 's', 't', 'r', 'i', 'n', 'g']

The fact that fun works for these inputs is more a coincidence, not by design. The inputs don't match the tested: a = [4, 5, 2]' and 'b = [3, 5, 4].

Look at what happens if the user puts spaces in the lists:

1355:~/mypy$ python3 stack56531390.py --list1 [4, 5, 2] --list2 [3,5,4] -o result
usage: stack56531390.py [-h] [--list1 LIST1] [--list2 LIST2] -o OUTLIST
stack56531390.py: error: unrecognized arguments: 5, 2]

or quotes to keep the spaced lists together:

1357:~/mypy$ python3 stack56531390.py --list1 "[4, 5, 2]" --list2 [3,5,4] -o result
['stack56531390.py', '--list1', '[4, 5, 2]', '--list2', '[3,5,4]', '-o', 'result']
Namespace(list1=['[', '4', ',', ' ', '5', ',', ' ', '2', ']'], list2=['[', '3', ',', '5', ',', '4', ']'], outlist='result')
[2, 3]

So while type=list can be made to work, it usually isn't a good choice. Remember, the argparse type is a function that is given a string; it's not a type or class specifier.

If I change the two arguments to take * inputs of type int:

ap.add_argument('--list1', nargs='*', type=int)
ap.add_argument('--list2', nargs='*', type=int)

1358:~/mypy$ python3 stack56531390.py --list1 4 5 2  --list2 3 5 4 -o result
['stack56531390.py', '--list1', '4', '5', '2', '--list2', '3', '5', '4', '-o', 'result']
Namespace(list1=[4, 5, 2], list2=[3, 5, 4], outlist='result')
[1, 1]

Now the two inputs are normal lists of integers, not those lists of characters that include brackets and commas. The comparison will be numeric, not lexical.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.