python argparse: unrecognized arguments

PythonArgparse

Python Problem Overview


When I run parsePlotSens.py -s bw hehe, it says that hehe is an unrecognized argument. However, if I run parsePlotSens.py hehe -s bw, it's OK. Ideally, I would like it work for both cases.

Any tips? The following is my code:

if __name__ == '__main__' :

    parser = argparse.ArgumentParser(prog='parsePlotSens');
    parser.add_argument('-s', '--sort', nargs =1, action = 'store', choices = ['mcs', 'bw'], default='mcs', help=sorthelp)
    parser.add_argument('filename', nargs ='+', action = 'store')
    option = parser.parse_args(sys.argv)

Python Solutions


Solution 1 - Python

Do not pass sys.argv as an argument to parse_args. Just use

option = parser.parse_args()

If you do pass sys.argv to parse_args, then the path or name of the script itself is the first item in sys.argv and thus becomes the value of option.filename. The hehe then becomes an unknown argument.

If you omit sys.argv then parse_args parses sys.argv as expected.

Solution 2 - Python

You can get around this by allowing unknown arguments

Replace

args = parser.parse_args()

with

args, unknown = parser.parse_known_args()

Solution 3 - Python

Also, as a complement to unutbu's answer, storing the arguments in a dictionary this way makes the tests easy:

args = vars(parser.parse_args())
print args

Prints the dictionary:

{'sort': ['bw'], 'filename': ['hehe']}

Like :

if args['sort'] == 'bw':
    # code here

...

Solution 4 - Python

My situation not same with the question, but the error is same.

My situation:

  1. I have a remote dev(SFTP) with windows pycharm, and upload to run with linux.

  2. the python command have some line break with \ in my bash file, like

     python args_config.py \
         --arg1="hello" \
         --arg2="world"
    

and raise a python argparse: unrecognized arguments args not found error.

the problem is the bash file line breaking is different in windows and linux,

just setting with pycharm File -> Line Separators -> LF - Unix and OS X (\n)

upload to linux and run bash file, it works!

Solution 5 - Python

To complete this answer here I provide an example to get and parse the unknown arguments:


import argparse

parser = argparse.ArgumentParser()
# we only have a know argument  as key-pair --known KNOWN
parser.add_argument('--known')

# test with known un unknown variables
args, unknown = parser.parse_known_args(["--known", "var", "--unknown", "bar", "--flag"])

unknown return a list like ["--unknown", "bar", "--flag"]. We just need to parse it:

keypairs = dict([unknown[i:i+2] for i in range(0, len(unknown), 1) if unknown[i].startswith("--") and not (unknown[i+1:i+2]+["--"])[0].startswith("--")])

flags = [unknown[i] for i in range(0, len(unknown), 2) if (unknown[i+1:i+2]+["--"])[0].startswith("--")]

Solution 6 - Python

Very useful thread. I had pretty much the same question as @Yan Zhu, @unutbu and @FacePalm's answeres were good, but I need to take in argv also. I came up with this, figured good because it allows me to write unit tests that don't require sys.argv arguments.

import argparse, sys


def parse(arg_list):
     p = argparse.ArgumentParser(description="my simple app")
     p.add_argument('-z', '--zeta', type=str, default='[zeta from default]')
     p.add_argument('-a', '--application', type=str, default='[application from default]')
     return p.parse_known_args(arg_list)


code_args = [ '-a', 'a from code', '-q', 'q from code', '-o', 'o from code']

print(parse(code_args + sys.argv[1:]))

When you add a runtime param from intellij like this -a 'a from intellij' the results look like so.

/usr/local/bin/python3.7 /Users/me/IdeaProjects/co-util-py/test/varargstest.py -a "a from intellij"

(Namespace(application='a from intellij', other='o from code'), ['-q', 'q from code'])

You can see that argparse doesn't drop the q, but it also doesn't parse it.

Also, after lots of brain strain and testing, the only real difference between sys.argv and a list created is that sys.argv[0] is the name of the program that is being called. Drop that from the list and it doesn't matter.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionYan ZhuView Question on Stackoverflow
Solution 1 - PythonunutbuView Answer on Stackoverflow
Solution 2 - PythonFacePalmView Answer on Stackoverflow
Solution 3 - PythonGauthier BoaglioView Answer on Stackoverflow
Solution 4 - PythonColin WangView Answer on Stackoverflow
Solution 5 - PythonaitorhhView Answer on Stackoverflow
Solution 6 - PythonTony FraserView Answer on Stackoverflow