Can you list the keyword arguments a function receives?

A little nicer than inspecting the code object directly and working out the variables is to use the inspect module.

>>> import inspect
>>> def func(a,b,c=42, *args, **kwargs): pass
>>> inspect.getargspec(func)
(['a', 'b', 'c'], 'args', 'kwargs', (42,))

If you want to know if its callable with a particular set of args, you need the args without a default already specified. These can be got by:

def getRequiredArgs(func):
    args, varargs, varkw, defaults = inspect.getargspec(func)
    if defaults:
        args = args[:-len(defaults)]
    return args   # *args and **kwargs are not required, so ignore them.

Then a function to tell what you are missing from your particular dict is:

def missingArgs(func, argdict):
    return set(getRequiredArgs(func)).difference(argdict)

Similarly, to check for invalid args, use:

def invalidArgs(func, argdict):
    args, varargs, varkw, defaults = inspect.getargspec(func)
    if varkw: return set()  # All accepted
    return set(argdict) - set(args)

And so a full test if it is callable is :

def isCallableWithArgs(func, argdict):
    return not missingArgs(func, argdict) and not invalidArgs(func, argdict)

(This is good only as far as python's arg parsing. Any runtime checks for invalid values in kwargs obviously can't be detected.)


This will print names of all passable arguments, keyword and non-keyword ones:

def func(one, two="value"):
    y = one, two
    return y
print func.func_code.co_varnames[:func.func_code.co_argcount]

This is because first co_varnames are always parameters (next are local variables, like y in the example above).

So now you could have a function:

def getValidArgs(func, argsDict):
    '''Return dictionary without invalid function arguments.'''
    validArgs = func.func_code.co_varnames[:func.func_code.co_argcount]
    return dict((key, value) for key, value in argsDict.iteritems() 
                if key in validArgs)

Which you then could use like this:

>>> func(**getValidArgs(func, args))

EDIT: A small addition: if you really need only keyword arguments of a function, you can use the func_defaults attribute to extract them:

def getValidKwargs(func, argsDict):
    validArgs = func.func_code.co_varnames[:func.func_code.co_argcount]
    kwargsLen = len(func.func_defaults) # number of keyword arguments
    validKwargs = validArgs[-kwargsLen:] # because kwargs are last
    return dict((key, value) for key, value in argsDict.iteritems() 
                if key in validKwargs)

You could now call your function with known args, but extracted kwargs, e.g.:

func(param1, param2, **getValidKwargs(func, kwargsDict))

This assumes that func uses no *args or **kwargs magic in its signature.


For a Python 3 solution, you can use inspect.signature and filter according to the kind of parameters you'd like to know about.

Taking a sample function with positional or keyword, keyword-only, var positional and var keyword parameters:

def spam(a, b=1, *args, c=2, **kwargs):
    print(a, b, args, c, kwargs)

You can create a signature object for it:

from inspect import signature
sig =  signature(spam)

and then filter with a list comprehension to find out the details you need:

>>> # positional or keyword
>>> [p.name for p in sig.parameters.values() if p.kind == p.POSITIONAL_OR_KEYWORD]
['a', 'b']
>>> # keyword only
>>> [p.name for p in sig.parameters.values() if p.kind == p.KEYWORD_ONLY]
['c']

and, similarly, for var positionals using p.VAR_POSITIONAL and var keyword with VAR_KEYWORD.

In addition, you can add a clause to the if to check if a default value exists by checking if p.default equals p.empty.