I'd like to use the ArgumentError
exception in the argparse
module in Python, but I can't figure out how to use it. The signature says that it should be called as ArgumentError(argument, message)
, but I can't figure out what argument
should be. I think it should be some part of the parser object, but I couldn't find any documentation for it.
-
2Related: [Is it bad form to raise `ArgumentError` by hand?](http://stackoverflow.com/q/8293325/1497596) – DavidRR Mar 12 '15 at 12:50
-
1You can use it within a custom `Action` class, just as the existing classes do. But I can't imagine a reason to do so outside of the `parser`. It doesn't anything special - just adds the `Action` name to the error message. Study its use in the code. – hpaulj Mar 12 '15 at 17:08
2 Answers
From the source documentation:
ArgumentError: The exception raised by ArgumentParser objects when there are errors with the parser's actions. Errors raised while parsing the command-line are caught by ArgumentParser and emitted as command-line messages.
The argument
parameter of the constructor is the Action
object from which the exception is raised. Usually there is no need to raise it outside of an Action
subclass, and when subclassing it, there is no need to raise it explicitly; you usually raise ValueError
(or whatever is appropriate) instead.
Float values between 0 and 1
In regards to your comment, that you only want to accept floating point values between 0 and 1. For this you should use the ability to define custom types. You can do it for example like this:
def percentFloat (string):
value = float(string)
if value < 0 or value > 1:
raise argparse.ArgumentTypeError('Value has to be between 0 and 1')
return value
parser = argparse.ArgumentParser()
parser.add_argument('test', type=percentFloat)
parser.parse_args()
Note that this is also safe against non-floats as float(string)
will raise a ValueError
for non-floats which also triggers an invalid type error by the argparse
module. ArgumentTypeError
is just a way to specify a custom error message.
Mutually exclusive parameters
For mutually exclusive parameters, you should use argparse.add_mutually_exclusive_group
.
Parameter dependency
Parameter dependency isn’t really something that should be done by the argument parser. For semantic details, you should instead simply do it yourself:
args = parser.parse_args()
if args.w and not args.p:
parser.error('-p is required when -w is set.')
You can use ArgumentParser.error
to raise custom error message which will interrupt the program and print to the console.
But of course in such a basic situation it would make a lot more sense just to implicitly guess -p
if possible.

- 369,085
- 72
- 557
- 602
-
2That isn't right. If I just send the value, I get `AttributeError: 'float' object has no attribute 'option_strings'`. – asmeurer Nov 12 '11 at 23:03
-
And by the way, I want to use it because I want to do type checking that the module doesn't directly support. For example, I want a floating point value that is between 0 and 1. argparse lets you specify that it should be a float, but I have to manually check the range. This seems like the correct error to emit when the value is wrong. – asmeurer Nov 12 '11 at 23:04
-
-
The downvote is because the answer is wrong. ArgumentError(1.1, "Value out of range") raises AttributeError, as I mentioned above. This needs to be some kind of internal argparse object, but I can't figure out what. And by the way, another example of when you might want to do this is when you want to define a non-trivial dependency on the arguments, which as far as I can tell, the argparse module does not directly support. Something like the `-w` option requires the `-p` option, or `-n` and `-N` are mutually exclusive. – asmeurer Nov 13 '11 at 20:56
While parser.error()
is what most people probably want, it is also possible to use argparse.ArgumentError() (as the question asks.) You need a reference to the argument, like the bar_arg
in the example below:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo')
bar_arg = parser.add_argument('--bar')
args = parser.parse_args()
if args.bar == 'xyzzy':
raise argparse.ArgumentError(bar_arg, "Can't be 'xyzzy'")
if args.foo == 'xyzzy':
parser.error("Can't be 'xyzzy'")
This will result in output like the one below:
$ python argparse_test.py --foo xyzzy
usage: argparse_test.py [-h] [--foo FOO] [--bar BAR]
argparse_test.py: error: Can't be 'xyzzy'
$ python argparse_test.py --bar xyzzy
Traceback (most recent call last):
File "argparse_test.py", line 10, in <module>
raise argparse.ArgumentError(bar_arg, "Can't be 'xyzzy'")
argparse.ArgumentError: argument --bar: Can't be 'xyzzy'

- 651
- 1
- 6
- 16

- 2,240
- 3
- 20
- 29
-
3This is a good example of how using `ArgumentError` outside of the `parser` is possible, but probably inferior to using `parser.error`. – hpaulj Mar 12 '15 at 19:03
-
@hpaulj, yes, but ArgumentError has one benefit: it lets you know which switch was the offending one. – ukrutt Mar 13 '15 at 11:42
-
1Well, if you write your error message well, then you'd be sure to _mention_ which switch was the offending one. Creating a separate variable for each added argument can be very cumbersome... – Praveen Sep 14 '16 at 22:55
-
1@Praveen It's a question of preference I suppose. Myself I prefer the variable to writing "'--foo' can't be 'xyzzy'", since I then have to remember what the proper name of the switch was (it's not necessarily the same as the attribute to `args`). But honestly, I think `parser.error()` should include the name of the offending switch by default. – ukrutt Sep 16 '16 at 16:23
-
1You can use `args.bar` as the argument to `ArgumentError`, not only `bar_arg`. – Yaroslav Nikitenko Feb 03 '21 at 11:56