python argparse: unrecognized arguments
PythonArgparsePython 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:
-
I have a remote dev(SFTP) with windows pycharm, and upload to run with linux.
-
the python command have some line break with
\
in my bash file, likepython 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.