Python: required kwarg, which exception to raise?
Question:
One way to ensure that a method is called with a particular kwarg would be like:
def mymethod(self, *args, **kwargs):
assert "required_field" in kwargs
Raising an AssertionError
doesn’t seem like the most appropriate thing to do. Is there an agreed upon builtin exception to handle this with a nice error message?
More info: there are 3rd-party subclassing issues where *args and **kwargs kinda’ need to be passed so making “required_field” a positional argument is not really a good option.
Answers:
>>> def foo(bar): pass
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() missing 1 required positional argument: 'bar'
I’d just go with TypeError..
The standard library seems to like to raise TypeError
when it gets the wrong number of arguments. That’s essentially your problem, so I’d raise that.
That said, **kwargs
essentially fill in for default arguments most of the time, so having a required default argument seems a little surprising/confusing.
Note that python will happily let you call positional arguments by keyword:
>>> def foo(a, b):
... print a, b
...
>>> foo(a=1, b=2)
1 2
>>> foo(b=1, a=2)
2 1
but I suppose that then they all have to be referenced by keyword (foo(2, a=2)
doesn’t work) which you may not want.
If you need it to be a required keyword, do something like:
def mymethod(self,myrequired=None):
if myrequired==None:
#raise error
#do other stuff down here
You shouldnt really need to pull it from kwargs.
I think KeyError
would be the most appropriate, because **kwargs
is a dict
.
>>> def foo(**kwargs):
... print kwargs['abc']
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
KeyError: 'abc'
If the field is actually required, you could check for it
try:
kwargs['required']
except KeyError:
raise KeyError('required is a Required Argument')
+1 for TypeError. This is what Python 3 raises for required keyword-only arguments:
>>> def foo(*, x):
... pass
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() needs keyword-only argument x
>>> foo(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() takes exactly 0 positional arguments (1 given)
>>> foo(x=2)
(TypeError suggestion was already given (and accepted); I wrote this answer to mention this Python 3 feature).
One way to ensure that a method is called with a particular kwarg would be like:
def mymethod(self, *args, **kwargs):
assert "required_field" in kwargs
Raising an AssertionError
doesn’t seem like the most appropriate thing to do. Is there an agreed upon builtin exception to handle this with a nice error message?
More info: there are 3rd-party subclassing issues where *args and **kwargs kinda’ need to be passed so making “required_field” a positional argument is not really a good option.
>>> def foo(bar): pass
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() missing 1 required positional argument: 'bar'
I’d just go with TypeError..
The standard library seems to like to raise TypeError
when it gets the wrong number of arguments. That’s essentially your problem, so I’d raise that.
That said, **kwargs
essentially fill in for default arguments most of the time, so having a required default argument seems a little surprising/confusing.
Note that python will happily let you call positional arguments by keyword:
>>> def foo(a, b):
... print a, b
...
>>> foo(a=1, b=2)
1 2
>>> foo(b=1, a=2)
2 1
but I suppose that then they all have to be referenced by keyword (foo(2, a=2)
doesn’t work) which you may not want.
If you need it to be a required keyword, do something like:
def mymethod(self,myrequired=None):
if myrequired==None:
#raise error
#do other stuff down here
You shouldnt really need to pull it from kwargs.
I think KeyError
would be the most appropriate, because **kwargs
is a dict
.
>>> def foo(**kwargs):
... print kwargs['abc']
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
KeyError: 'abc'
If the field is actually required, you could check for it
try:
kwargs['required']
except KeyError:
raise KeyError('required is a Required Argument')
+1 for TypeError. This is what Python 3 raises for required keyword-only arguments:
>>> def foo(*, x):
... pass
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() needs keyword-only argument x
>>> foo(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: foo() takes exactly 0 positional arguments (1 given)
>>> foo(x=2)
(TypeError suggestion was already given (and accepted); I wrote this answer to mention this Python 3 feature).