How to get function string name from i-th stack position?

Ian Kelly ian.g.kelly at gmail.com
Sat Dec 31 12:13:08 EST 2011


On Sat, Dec 31, 2011 at 1:44 AM, dmitrey <dmitrey15 at gmail.com> wrote:
> On Dec 30, 11:48 pm, Ian Kelly <ian.g.ke... at gmail.com> wrote:
>> On Fri, Dec 30, 2011 at 11:43 AM, dmitrey <dmitre... at gmail.com> wrote:
>> > Thank you. And what should I do to get function by itself instead of
>> > its string name, e.g. I want to know does this function is my_func or
>> > any other? For example, I would like to check is this function Python
>> > sum(), or maybe numpy.sum(), or anything else?
>>
>> The Python stack only includes Python code objects.  Built-ins like
>> sum won't appear in it because they're basically C functions and don't
>> have associated code objects.  If you really want to see them, you
>> could probably do something with ctypes to inspect the C stack, but I
>> don't recommend it.
>>
>> You can get the Python code objects from the stack by calling
>> inspect.stack(), which includes each frame object currently on the
>> stack as the first member of each tuple.  E.g.:
>>
>> frames = map(operator.itemgetter(0), inspect.stack())
>>
>> Each frame has an f_code attribute that stores the code object
>> associated with that frame.  Getting the actual function from the code
>> object is tricky, for two reasons.  One, not all code objects
>> represent functions.  There are also code objects for modules, class
>> definitions, and probably other thing as well.  Two, code objects
>> don't have associated functions. The relationship is the reverse:
>> functions have associated code objects.  You would have to iterate
>> over each function that you're interested in, looking for one with a
>> func_code attribute that "is" the frame's f_code attribute.
>>
>> In any case, testing function identity is a rather large rabbit hole
>> that is best avoided.  These are mathematically the same function:
>>
>> def plus1(value):
>>     return value + 1
>>
>> plus_one = lambda x: x + 1
>>
>> But they are two distinct function objects, and there is no way
>> programmatically to determine that they are the same function except
>> by comparing the bytecode (which won't work generally because of the
>> halting problem).
>>
>> What is it that you're trying to do?  Perhaps the helpful folks on the
>> list will be able to suggest a better solution if you can provide more
>> details.
>>
>> Cheers,
>> Ian
>
> Maybe it is somehow possible to compare function id with my candidates
> id, e.g.
> PythonSumID = id(sum)
> import numpy
> NumpySumID = id(numpy.sum)
> func = getting_function_from_Nth_stack_level_above
> if id(func) == PythonSumID:
>  ....
> elif id(func) == NumpySumID:
>  ....
> else:
>  ....
> I need it due to the following reason: FuncDesigner users often use
> Python or numpy sum on FuncDesigner objects, while FuncDesigner.sum()
> is optimized for this case, works faster and doesn't lead to "Max
> recursion dept exceeded", that sometimes trigger for numpy or Python
> sum() when number of summarized elements is more than several
> hundreds. I would like to print warning "you'd better use FuncDesigner
> sum" if this case has been identified.

The only think I can think of would be to replace the sum built-in
with a wrapper that checks whether it's being called on FuncDesigner
objects and issues a warning.  Users might not like you messing with
their built-ins in that way, though.



More information about the Python-list mailing list