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.

Asked By: Skylar Saveland

||

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..

Answered By: Otto Allmendinger

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.

Answered By: mgilson

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.

Answered By: IT Ninja

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')     
Answered By: munk

+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).

Answered By: Mikhail Korobov
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.