inspecting a callable for the arguments it accepts

Chris Angelico rosuav at gmail.com
Tue Nov 14 17:12:08 EST 2017


On Wed, Nov 15, 2017 at 8:05 AM, Cameron Simpson <cs at cskk.id.au> wrote:
> I know that this isn't generally solvable, but I'm wondering if it is
> partially solvable.
>
> I have a task manager which accepts callables, usually functions or
> generators, and calls them on data items as needed. For reasons which,
> frankly, suggest user interface ergonomics failure to me it happens that
> inappropriate functions get submtted to this system. For example, functions
> accepting no arguments but which are handed one by the system.
>
> I would like to inspect submitted functions' signatures for suitability at
> submission time, without calling the function. For example to see if this
> function accepts exactly one argument, or to see if it is a generator, etc.
>
> Is this possible, even in a limited way?

Yes, it is. Sometimes in a very limited way, other times fairly well.
(NOTE: I'm using CPython for this. Other interpreters may differ
wildly.) First off, you can look at the function's attributes to see
some of the info you want:

>>> def wants_one_arg(x): pass
...
>>> wants_one_arg.__code__.co_argcount
1
>>> wants_one_arg.__code__.co_varnames
('x',)

co_varnames has the names of all local variables, and the first N of
those are the arguments. You aren't matching on the argument names,
but they might help you make more readable error messages.

As to recognizing generators, every function has a set of flags which
will tell you whether it yields or just returns:

>>> def fun(): pass
...
>>> def gen(): yield 1
...
>>> fun.__code__.co_flags
67
>>> gen.__code__.co_flags
99

That's the raw info. For human-friendly functions that look at this
info, check out the inspect module:

>>> inspect.isgeneratorfunction(fun)
False
>>> inspect.isgeneratorfunction(gen)
True
>>> inspect.signature(wants_one_arg)
<Signature (x)>

Poke around with its functions and you should be able to find most of
what you want, I think.

ChrisA



More information about the Python-list mailing list