Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #93198 > unrolled thread
| Started by | georgeryoung@gmail.com |
|---|---|
| First post | 2015-06-26 10:12 -0700 |
| Last post | 2015-06-26 18:44 +0100 |
| Articles | 3 — 3 participants |
Back to article view | Back to comp.lang.python
how to replace some methods with instrumented ones georgeryoung@gmail.com - 2015-06-26 10:12 -0700
Re: how to replace some methods with instrumented ones Peter Otten <__peter__@web.de> - 2015-06-26 19:37 +0200
Re: how to replace some methods with instrumented ones MRAB <python@mrabarnett.plus.com> - 2015-06-26 18:44 +0100
| From | georgeryoung@gmail.com |
|---|---|
| Date | 2015-06-26 10:12 -0700 |
| Subject | how to replace some methods with instrumented ones |
| Message-ID | <1bd45a06-6141-429d-89bc-79b5aa7de0ff@googlegroups.com> |
[python 2.7, linux]
I have a python app. I cannot modify the file. But I can import it and mess with it. I need to perform brief tasks before and after some of the member functions.
I'd like to do this in as clear and maintainable way as possible (no third party imports). Here's what I have now(which works):
from newvbr import * #get all the stuff from the newvbr app.
def perf_time(tag): # I do a little more than this, but you get the idea.
print >>sys.stderr, datetime.datetime.now().isoformat() + tag
def perf(tag):
def decorator(fn):
def wrapper(*args):
perf_time('start %s' % tag)
ret = fn(*args)
perf_time('end %s' % tag)
return ret
return wrapper
return decorator
I use this on various members of various classes in the newvbr app:
old_database_snapshot = VerticaSession.database_snapshot
@perf('db_snap')
def new_database_snapshot(self, name):
old_database_snapshot(self, name)
VerticaSession.database_snapshot = new_database_snapshot
old_object_snapshot = VerticaSession.object_snapshot
@perf('obj_snap')
def new_object_snapshot(self, name):
old_object_snapshot(self, name)
VerticaSession.object_snapshot = new_object_snapshot
main() #do the usual stuff of the imported app, but with annotations.
This is still pretty laborious. How can I make something roughly like:
super_tagger(VerticaSession.database_snapshot)
that does all the above? I need to tag a bunch of function members like this. I don't insist on using decorators, it just looked like that kind of problem.
[toc] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2015-06-26 19:37 +0200 |
| Message-ID | <mailman.107.1435340255.3674.python-list@python.org> |
| In reply to | #93198 |
georgeryoung@gmail.com wrote:
> [python 2.7, linux]
> I have a python app. I cannot modify the file. But I can import it and
> mess with it. I need to perform brief tasks before and after some of the
> member functions.
> I'd like to do this in as clear and maintainable way as possible (no third
> party imports). Here's what I have now(which works):
>
> from newvbr import * #get all the stuff from the newvbr app.
>
> def perf_time(tag): # I do a little more than this, but you get the idea.
> print >>sys.stderr, datetime.datetime.now().isoformat() + tag
>
> def perf(tag):
> def decorator(fn):
> def wrapper(*args):
> perf_time('start %s' % tag)
> ret = fn(*args)
> perf_time('end %s' % tag)
> return ret
> return wrapper
> return decorator
>
>
> I use this on various members of various classes in the newvbr app:
>
> old_database_snapshot = VerticaSession.database_snapshot
> @perf('db_snap')
> def new_database_snapshot(self, name):
> old_database_snapshot(self, name)
> VerticaSession.database_snapshot = new_database_snapshot
>
> old_object_snapshot = VerticaSession.object_snapshot
> @perf('obj_snap')
> def new_object_snapshot(self, name):
> old_object_snapshot(self, name)
> VerticaSession.object_snapshot = new_object_snapshot
>
> main() #do the usual stuff of the imported app, but with annotations.
>
>
> This is still pretty laborious. How can I make something roughly like:
>
> super_tagger(VerticaSession.database_snapshot)
>
> that does all the above? I need to tag a bunch of function members like
> this. I don't insist on using decorators, it just looked like that kind
> of problem.
Remember that
@foo
def bar(...):
...
is just syntactic sugar for
def bar(...): ...
bar = foo(bar)
In your case the latter form is more convenient, so instead of
> old_object_snapshot = VerticaSession.object_snapshot
> @perf('obj_snap')
> def new_object_snapshot(self, name):
> old_object_snapshot(self, name)
> VerticaSession.object_snapshot = new_object_snapshot
use
VerticalSession.object_snapshot = perf("obj_snap")(VerticalSession.object_snapshot)
If you like you can write a helper function along these lines
def wrap_attr(obj, attrname, name=None):
if name is None:
name = attrname
setattr(obj, attrname
perf(name)(getattr(obj, attrname)))
wrap_attr(VerticalSession, "object_snapshot")
[toc] | [prev] | [next] | [standalone]
| From | MRAB <python@mrabarnett.plus.com> |
|---|---|
| Date | 2015-06-26 18:44 +0100 |
| Message-ID | <mailman.108.1435340694.3674.python-list@python.org> |
| In reply to | #93198 |
On 2015-06-26 18:12, georgeryoung@gmail.com wrote:
> [python 2.7, linux]
> I have a python app. I cannot modify the file. But I can import it and mess with it. I need to perform brief tasks before and after some of the member functions.
> I'd like to do this in as clear and maintainable way as possible (no third party imports). Here's what I have now(which works):
>
> from newvbr import * #get all the stuff from the newvbr app.
>
> def perf_time(tag): # I do a little more than this, but you get the idea.
> print >>sys.stderr, datetime.datetime.now().isoformat() + tag
>
> def perf(tag):
> def decorator(fn):
> a def wrapper(*args):
> perf_time('start %s' % tag)
> ret = fn(*args)
> perf_time('end %s' % tag)
> return ret
> return wrapper
> return decorator
>
>
> I use this on various members of various classes in the newvbr app:
>
> old_database_snapshot = VerticaSession.database_snapshot
> @perf('db_snap')
> def new_database_snapshot(self, name):
> old_database_snapshot(self, name)
> VerticaSession.database_snapshot = new_database_snapshot
>
> old_object_snapshot = VerticaSession.object_snapshot
> @perf('obj_snap')
> def new_object_snapshot(self, name):
> old_object_snapshot(self, name)
> VerticaSession.object_snapshot = new_object_snapshot
>
> main() #do the usual stuff of the imported app, but with annotations.
>
>
> This is still pretty laborious. How can I make something roughly like:
>
> super_tagger(VerticaSession.database_snapshot)
>
> that does all the above? I need to tag a bunch of function members like this. I don't insist on using decorators, it just looked like that kind of problem.
>
You could do something like this:
def super_tagger(module, function_name, tag):
original_function = getattr(module, function_name)
@perf(tag)
def wrapper(*args, **kwargs):
return original_function(*args, **kwargs)
setattr(module, function_name, wrapper)
and then:
super_tagger(VerticaSession, 'database_snapshot', 'db'snap')
It might be cleaner to merge the functionality of 'perf' into it:
def super_tagger(module, function_name, tag):
original_function = getattr(module, function_name)
def wrapper(*args, **kwargs):
perf_time('start %s' % tag)
result = original_function(*args, **kwargs)
perf_time('end %s' % tag)
return result
setattr(module, function_name, wrapper)
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web