87

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)
alex
7,59612 gold badges62 silver badges116 bronze badges
asked Jun 15, 2013 at 0:14

6 Answers 6

106

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.

answered Jun 15, 2013 at 0:35
Sign up to request clarification or add additional context in comments.

4 Comments

Alternatively you can call parser.parse_args(sys.argv[1:]). Internally argparse does just that.
@MarioVilas now why in the world would you want to reimplement something that is handled by the library you're using? There is no reason to pick this option over omitting sys.argv altogether
@aidandeno MarioVilas comment could be useful for someone who wants to call a function they've written that calls argparse.ArgumentParser and gets the arguments for argparse.ArgumentParser from its parameters. For example, maybe someone wants to know how to call theirArgumentHandlerFunction without getting "unrecognized arguments" - by calling it like MarioVilas comment suggests, as theirArgumentHandlerFunction(sys.argv[1:]).
@MarioVilas When writing unit tests, it's better to pass the argv into the function instead of overriding the value of sys.argv.
93

You can get around this by allowing unknown arguments

Replace

args = parser.parse_args()

with

args, unknown = parser.parse_known_args()
answered Jan 2, 2018 at 7:58

Comments

4

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
...
answered Jun 15, 2013 at 0:24

1 Comment

That's always False because the string 'bw' will never be equal to a list with that string in it. I fail to see the reason to use vars() here. If you omit that pointless conversion the test becomes if args.sort == 'bw':. That's how it is supposed to be used.
3

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("--")]
Benjamin Loison
5,7704 gold badges20 silver badges37 bronze badges
answered Aug 20, 2019 at 21:18

Comments

2

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!

answered Nov 10, 2018 at 8:56

Comments

1

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.

answered May 4, 2020 at 17:03

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.