Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: Wrap and intercept function calls

4 views
Skip to first unread message

Terry Reedy

unread,
Feb 17, 2010, 3:57:57 PM2/17/10
to pytho...@python.org
On 2/17/2010 11:04 AM, Dan Yamins wrote:
> Really, nobody has any idea about this? (Sorry to repost.)

> On Tue, Feb 16, 2010 at 7:29 PM, Dan Yamins <dya...@gmail.com
> <mailto:dya...@gmail.com>> wrote:
>
> Hi:
>
> I'm wondering what the best way to wrap and modify function calls
> is. Essentially what I want to achieve is to have a function like
> this:
>
> def Wrap(frame,event,arg):
> if event == 'call':
> result = PerformCheck(GetArgumentsFromFrame(frame))
> if Condition(result):
> return result
> else:
> return [normal function call]
>
> called whenever a "call" event is about to occur.

For yourself as interpreter, execute the above for every call.

For CPython, alternative 1 is to create a custom interpreter to change
(wrap) the interpretation of the call-function bytecode in the ceval
loop. That is its 'call event', and I believe this would catch every
explicit f(args) call and only such calls.

Python has no general metasyntax for changing the semantics of its
syntax. The __xx__ methods are special cases for the corresponding
operators *and* the corresponding user-defined class. The '__call__'
method of a class applies to instances of that class. Alternative 2:

class func_wrap:
def __init__(self, func):
self._func = func
def __call__(self, args, kwds):
result = PerformCheck(args, kwds)
if Condition(result):
return result
else:
return self._func(*args,**kwds)

Now wrap *every* function you are interested in. Builtin functions are
no problem; methods of builtin classes cannont be wrapped without
subclassing.

Terry Jan Reedy

> When I say "return result" I mean: return that data object instead
> of what the function would have returned, and prevent execution of
> the function.
>
> Is there any way to do this using sys.settrace? Or perhaps
> something from the bdb or pbd module?
>
>
> In other words, what I'm looking for is a way to intercept all function
> calls with a "wrapper" -- like one can do using settrace and other
> debugging methods -- but, unlike the debugging methods, have the
> "wrapping" function actually be able to intervene in the stack and, for
> instance, conditionally replace the function call's return with
> something determined in the wrapping function and prevent the function
> call's execution. I want to be able to do this by setting a single
> system-wide (or at any rate, thread-wide) value, like with settrace, and
> not have to modify individual functions one by one.
>
> Could I, for example, set a settrace function that somehow modifies the
> stack? Or is there some much better way to do this? Or, if someone can
> tell me that this can't be done without having to roll my own
> implementation of the Python interpreter, that would be great to know too.
>
> Thanks again,
> Dan
>


geremy condra

unread,
Feb 17, 2010, 8:44:11 PM2/17/10
to yam...@fas.harvard.edu, pytho...@python.org
On Wed, Feb 17, 2010 at 11:04 AM, Dan Yamins <dya...@gmail.com> wrote:
> Really, nobody has any idea about this?   (Sorry to repost.)
>
> On Tue, Feb 16, 2010 at 7:29 PM, Dan Yamins <dya...@gmail.com> wrote:
>>
>> Hi:
>>
>> I'm wondering what the best way to wrap and modify function calls is.
>> Essentially what I want to achieve is to have a function like this:
>>
>> def Wrap(frame,event,arg):
>>      if event == 'call':
>>         result = PerformCheck(GetArgumentsFromFrame(frame))
>>         if Condition(result):
>>             return result
>>         else:
>>             return [normal function call]
>>
>> called whenever a "call" event is about to occur.
>>
>> When I say "return result" I mean:  return that data object instead of
>> what the function would have returned, and prevent execution of the
>> function.
>>
>> Is there any way to do this using sys.settrace?  Or perhaps something from
>> the bdb or pbd module?
>>
>
> In other words, what I'm looking for is a way to intercept all function
> calls with a "wrapper" --  like one can do using settrace and other
> debugging methods -- but, unlike the debugging methods, have the "wrapping"
> function actually be able to intervene in the stack and, for instance,
> conditionally replace the function call's return with something determined
> in the wrapping function and prevent the function call's execution.   I want
> to be able to do this by setting a single system-wide (or at any rate,
> thread-wide) value, like with settrace, and not have to modify individual
> functions one by one.
>
> Could I, for example, set a settrace function that somehow modifies the
> stack?  Or is there some much better way to do this?  Or, if someone can
> tell me that this can't be done without having to roll my own implementation
> of the Python interpreter, that would be great to know too.
>
> Thanks again,
> Dan
>
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>
>

You could drill down through everything in globals() etc, replacing
functions as you went,
but its fragile (there are probably unworkable corner cases), ugly,
and likely to be slow.
What exactly is it you're trying to do?

Geremy Condra

alex23

unread,
Feb 17, 2010, 9:42:44 PM2/17/10
to
Terry Reedy <tjre...@udel.edu> wrote:
> Now wrap *every* function you are interested in. Builtin functions are
> no problem; methods of builtin classes cannont be wrapped without
> subclassing.

It's a shame it's not possible to do:

type.__call__ = func_wrap(type.__call__)

Or even:

type.__class__ = NewType

0 new messages