[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.python

inspect.stack() and frame

Félix-Antoine Fortin

3/11/2010 11:05:00 PM

Given this code :
# Experience with frame
import sys
import inspect

def foo():
stack = inspect.stack()
print "foo frame : " + str(hex(id(sys._getframe())))

def foo2():
inspect.stack()
print "foo2 frame : " + str(hex(id(sys._getframe())))

def bar():
print "bar frame : " + str(hex(id(sys._getframe())))

foo()
foo()

foo2()
foo2()

bar()
bar()

Output example :
foo frame : 0x84d2c0
foo frame : 0x844bf0
foo2 frame : 0x898c90
foo2 frame : 0x898c90
bar frame : 0x898f70
bar frame : 0x898f70

Why are the ids (address) of the frame for each foo call not the same?
Or why the call to "stack = inspect.stack()" change the address of the
frame?
4 Answers

Alf P. Steinbach

3/11/2010 11:22:00 PM

0

* Félix-Antoine Fortin:
> Given this code :
> # Experience with frame
> import sys
> import inspect
>
> def foo():
> stack = inspect.stack()
> print "foo frame : " + str(hex(id(sys._getframe())))

hex returns a string. applying str is therefore redundant.


> def foo2():
> inspect.stack()
> print "foo2 frame : " + str(hex(id(sys._getframe())))
>
> def bar():
> print "bar frame : " + str(hex(id(sys._getframe())))
>
> foo()
> foo()
>
> foo2()
> foo2()
>
> bar()
> bar()
>
> Output example :
> foo frame : 0x84d2c0
> foo frame : 0x844bf0
> foo2 frame : 0x898c90
> foo2 frame : 0x898c90
> bar frame : 0x898f70
> bar frame : 0x898f70
>
> Why are the ids (address) of the frame for each foo call not the same?

You're dealing with Python objects. You're not dealing with the computer's
machine stack. Whether you get the same id for two objects whose lifetimes don't
overlap depends on the implementation's memory and id allocation strategy.


> Or why the call to "stack = inspect.stack()" change the address of the
> frame?

Does it?


Cheers,

- Alf

Félix-Antoine Fortin

3/12/2010 12:03:00 AM

0

On Mar 11, 6:22 pm, "Alf P. Steinbach" <al...@start.no> wrote:
> * F lix-Antoine Fortin:
>
> > Given this code :
> > # Experience with frame
> > import sys
> > import inspect
>
> > def foo():
> >     stack = inspect.stack()
> >     print "foo frame : " + str(hex(id(sys._getframe())))
>
> hex returns a string. applying str is therefore redundant.
>

My bad.

>
>
>
>
> > def foo2():
> >     inspect.stack()
> >     print "foo2 frame : " + str(hex(id(sys._getframe())))
>
> > def bar():
> >     print "bar frame : " + str(hex(id(sys._getframe())))
>
> > foo()
> > foo()
>
> > foo2()
> > foo2()
>
> > bar()
> > bar()
>
> > Output example :
> > foo frame : 0x84d2c0
> > foo frame : 0x844bf0
> > foo2 frame : 0x898c90
> > foo2 frame : 0x898c90
> > bar frame : 0x898f70
> > bar frame : 0x898f70
>
> > Why are the ids (address) of the frame for each foo call not the same?
>
> You're dealing with Python objects. You're not dealing with the computer's
> machine stack. Whether you get the same id for two objects whose lifetimes don't
> overlap depends on the implementation's memory and id allocation strategy.
>

Okay, I thought I got that when I read the id documentation, but now I
get it.
So the only to compare two ids, is by making sure their lifetimes
overlap. In
this case, instead of keeping the ids, I have to keep a reference on
the frame
to make sure it is still alive when I will compare it with a second
one.

Thanks!

> > Or why the call to "stack = inspect.stack()" change the address of the
> > frame?
>
> Does it?
>

Yeah it does... I always get N different id when I run foo() N times
in a row.
Actually, what you said about lifetime applies here too. Here is
another quick
snippet :

import sys
import inspect

def foo():
stack = inspect.stack()
return sys._getframe()

def foo2():
stack = inspect.stack()
del stack
return sys._getframe()

def bar():
inspect.stack()
return sys._getframe()

frame_foo = foo()
frame_foo2 = foo2()
frame_bar = bar()

print sys.getrefcount(frame_foo)
print sys.getrefcount(frame_foo2)
print sys.getrefcount(frame_bar)

Output :
3
2
2

So it seems that there is one more reference to the foo frame because
only because of "stack = inspect.stack()", so its lifetime isn't done
contrary to foo2 and bar frame, and the frame id of a foo frame is
different for each call.

Now, what is keeping a reference on foo frame?

Thanks Alf,

Felix

Félix-Antoine Fortin

3/12/2010 2:08:00 PM

0

Thanks Gabriel, you resumed quite well what I did discovered after my
second post
by playing with the garbage collector module.

> (The garbage collector will,  
> eventually, break the cycle and free those objects, but not very soon).

I'm not very familiar with the Python garbage collector, so you may
excuse my
simple question, but how can it break the cycle? I guess the object
will be
freed at least when the program ends, but could it be before that? Is
there a
mechanisme in the garbage collector to detect circular references?

Felix


MRAB

3/12/2010 3:47:00 PM

0

Félix-Antoine Fortin wrote:
> Thanks Gabriel, you resumed quite well what I did discovered after my
> second post
> by playing with the garbage collector module.
>
>> (The garbage collector will,
>> eventually, break the cycle and free those objects, but not very soon).
>
> I'm not very familiar with the Python garbage collector, so you may
> excuse my
> simple question, but how can it break the cycle? I guess the object
> will be
> freed at least when the program ends, but could it be before that? Is
> there a
> mechanisme in the garbage collector to detect circular references?
>
In CPython objects are reference-counted, which allows an object to be
collected as soon as there are no references to it.

However, this won't take care of circular references, so a secondary
garbage collector was introduced which occasionally looks for
inaccessible objects (garbage) using (probably) mark-and-sweep.