473,386 Members | 1,812 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,386 software developers and data experts.

finding out the call (and not only the caller)

Hi,

Today I've been thinking a bit about the "python internals". Inspired
by this recipe:
http://aspn.activestate.com/ASPN/Coo...n/Recipe/66062
I found out a little problem which haven't been able to solve.
In short, is there a way to find out how a given name lookup was started?
It is not enough to know the name of the caller as given by the recipe.

a little example:
import inspect

class test(object):
def __init__(self, a_list):
self.my_list = a_list
def info(self):
for counter, item in
enumerate(inspect.getouterframes(inspect.currentfr ame())):
print counter, item
return self.my_list
data = property(info)

if __name__ == '__main__':
a = test([1111,2222])
def g(a_seq):
for item in a_seq:
print item, '\n'
g(a.data)

This prints
0 (<frame object at 0x00B58B08>, 'myfile.py', 10, 'info', ['
for counter, item in
enumerate(inspect.getouterframes(inspect.currentfr ame())):\n'], 0)
1 (<frame object at 0x00A5B000>, 'myfile.py', 38, '<module>', ['
g(a.data)\n'], 0)
1111
2222

What I would like is a reference to g itself, and not only to
'<module>' which is the caller according to f_code.co_name.
I thought of manually parsing the string ' g(a.data)\n' to extract
the name but I'm sure that it would be a rather fragile approach, and
so I decided that it was time to ask for help :-)
To 'get a feeling', I tried to disassemble the code:

code = compile('g(a.data)', 'test', 'single')
dis.dis(code)

and this is the result

0 LOAD_NAME 0 (g)
3 LOAD_NAME 1 (a)
6 LOAD_ATTR 2 (data)
9 CALL_FUNCTION 1
12 PRINT_EXPR
13 LOAD_CONST 0 (None)
16 RETURN_VALUE

So ... I'm looking for the first name loaded. Is there a reference to
it, somewhere?

Francesco
Oct 7 '07 #1
3 1348
On Oct 7, 2:47 pm, "Francesco Guerrieri" <f.guerri...@gmail.com>
wrote:
Hi,

Today I've been thinking a bit about the "python internals". Inspired
by this recipe:http://aspn.activestate.com/ASPN/Coo...n/Recipe/66062
I found out a little problem which haven't been able to solve.
In short, is there a way to find out how a given name lookup was started?
If you constrain the problem, yes, it's possible. However, the
solution below is limited to CPython and has other limits.
It is not enough to know the name of the caller as given by the recipe.

a little example:
import inspect

class test(object):
def __init__(self, a_list):
self.my_list = a_list
def info(self):
for counter, item in
enumerate(inspect.getouterframes(inspect.currentfr ame())):
print counter, item
return self.my_list
data = property(info)

if __name__ == '__main__':
a = test([1111,2222])
def g(a_seq):
for item in a_seq:
print item, '\n'
g(a.data)

This prints
0 (<frame object at 0x00B58B08>, 'myfile.py', 10, 'info', ['
for counter, item in
enumerate(inspect.getouterframes(inspect.currentfr ame())):\n'], 0)
1 (<frame object at 0x00A5B000>, 'myfile.py', 38, '<module>', ['
g(a.data)\n'], 0)
1111
2222

What I would like is a reference to g itself, and not only to
'<module>' which is the caller according to f_code.co_name.
I thought of manually parsing the string ' g(a.data)\n' to extract
the name but I'm sure that it would be a rather fragile approach, and
so I decided that it was time to ask for help :-)
To 'get a feeling', I tried to disassemble the code:

code = compile('g(a.data)', 'test', 'single')
dis.dis(code)

and this is the result

0 LOAD_NAME 0 (g)
3 LOAD_NAME 1 (a)
6 LOAD_ATTR 2 (data)
9 CALL_FUNCTION 1
12 PRINT_EXPR
13 LOAD_CONST 0 (None)
16 RETURN_VALUE

So ... I'm looking for the first name loaded. Is there a reference to
it, somewhere?
#!/usr/bin/python

import sys, opcode
def WhoCalledMe(a, *args, **kwargs):
# Get the calling frame and the bytecode index of the last
instruction.
f = sys._getframe(1)
lasti = f.f_lasti
code = f.f_code.co_code

# TODO: Needs to be extended for the other 3 variants of
CALL_FUNCTION.
assert ord(code[lasti]) == opcode.opmap['CALL_FUNCTION']
# Get the number of arguments the function was called with.
num_args = ord(code[lasti+1])
num_kwargs = ord(code[lasti+2])

# Get the instruction that loaded the object being called.
# Work backwards from the function call. 3 is the size of each
LOAD_* op
# (assuming EXTENDED_ARG is not used). 1 for the previous opcode,
# number of positional arguments, and 2 for kwargs (1 for the name,
# 1 for the value).
i = lasti - 3 * (1 + num_args + 2 * num_kwargs)
# Again, this assumes EXTENDED_ARG is not used.
load_index = ord(code[i+1]) + (ord(code[i+2]) << 8)

# Another assumption that isn't always true, but convenient for our
case.
opname = opcode.opname[ord(code[i])]
assert opname.startswith('LOAD_')

# Get the name of the variable and its value.
name = value = None
if opname in ('LOAD_FAST', 'LOAD_NAME'):
try:
name = f.f_code.co_varnames[load_index]
value = f.f_locals[name]
except LookupError:
assert opname == 'LOAD_NAME'
# opname must be LOAD_NAME and the variable is a global, ignore
it.

if opname in ('LOAD_GLOBAL', 'LOAD_NAME') and not name:
try:
name = f.f_code.co_names[load_index]
value = f.f_globals[name]
except LookupError:
print 'Uh-oh. Should have found the name in globals.'
# TODO: handle LOAD_CONST, LOAD_DEREF and LOAD_CLOSURE.

print 'Called by', name, 'value is', value
def main():
WhoCalledMe(0)

MeDammit = WhoCalledMe
MeDammit(1, k1=1, k2=2)
if __name__ == '__main__':
main()

WhoCalledMe(0)

MeDammit = WhoCalledMe
MeDammit(1, k1=1, k2=2)

# end of script

If you run the scrit above, it should print something like:

Called by WhoCalledMe value is <function WhoCalledMe at
0x2ac718dff6e0>
Called by MeDammit value is <function WhoCalledMe at 0x2ac718dff6e0>
Called by WhoCalledMe value is <function WhoCalledMe at
0x2ac718dff6e0>
Called by MeDammit value is <function WhoCalledMe at 0x2ac718dff6e0>

The code doesn't handle all the cases (e.g., nested functions), but
gives you an idea of what can be done and where to look for the info
(ie, in the stack frame and how to parse the byte codes to some
extent). For nested functions, look in co_consts.

Bytecodes are specific to CPython. This code won't work on
IronPython, Jython, or PyPy. This code really shouldn't be used for
production. However, it demonstrates some of the info available.

n

Oct 9 '07 #2
Hi Neal,

nn******@gmail.com wrote:
The code doesn't handle all the cases (e.g., nested functions), but
gives you an idea of what can be done and where to look for the info
(ie, in the stack frame and how to parse the byte codes to some
extent). For nested functions, look in co_consts.

Bytecodes are specific to CPython. This code won't work on
IronPython, Jython, or PyPy. This code really shouldn't be used for
production. However, it demonstrates some of the info available.
Actually that's not true for PyPy. PyPy uses CPython's bytecode, so the
example works just fine.

Cheers,

Carl Friedrich Bolz
Oct 28 '07 #3
Hi Neal,

nn******@gmail.com wrote:
The code doesn't handle all the cases (e.g., nested functions), but
gives you an idea of what can be done and where to look for the info
(ie, in the stack frame and how to parse the byte codes to some
extent). For nested functions, look in co_consts.

Bytecodes are specific to CPython. This code won't work on
IronPython, Jython, or PyPy. This code really shouldn't be used for
production. However, it demonstrates some of the info available.
Actually that's not true for PyPy. PyPy uses CPython's bytecode, so the
example works just fine.

Cheers,

Carl Friedrich Bolz

Oct 28 '07 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Gnanaprakash Rathinam | last post by:
Hi Expert, Is there a way to obtain assembly name in an unmanaged call? During Interop call between managed to unmanaged, I would like to know in unmanaged code about the caller of assembly file...
0
by: Trey | last post by:
I am trying to make a database for tracking calls, the caller gets one free call (per 12 months), then is charged a flat fee for every call after the first call in a 12 month time span. The data is...
4
by: Pekka Henttonen | last post by:
Let's say there is an object which has several methods all taking different object as argument: class TestObject { public void SetTitle( TitleObject title ); public void SetDate( DateObject...
1
by: Atara | last post by:
In my WindowForms Application I have Control1 inside Control2 inside Control3 inside theMainForm. I have a scenario that Control1 should call/sendEvent to theMainForm. in response, theMainForm...
13
by: mitchellpal | last post by:
i am really having a hard time trying to differentiate the two..........i mean.....anyone got a better idea how each occurs?
2
by: lcaamano | last post by:
We have a tracing decorator that automatically logs enter/exits to/from functions and methods and it also figures out by itself the function call arguments values and the class or module the...
3
by: Rico | last post by:
Hello, I have a generic process that logs errors from different sources. When I call this code, I'd like to also submit the name of the function or sub that is raising the error without having...
3
by: | last post by:
Is it possible to have just a multithreaded sub procedure? What I need is a timer time_elapsed event (2 sec interval) send params to a sub that is multithreaded. I have a COM component used to...
275
by: Astley Le Jasper | last post by:
Sorry for the numpty question ... How do you find the reference name of an object? So if i have this bob = modulename.objectname() how do i find that the name is 'bob'
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.