Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Stagnant Frame Data?

Reply
Thread Tools

Stagnant Frame Data?

 
 
Mike
Guest
Posts: n/a
 
      11-15-2009
I'll apologize first for this somewhat lengthy example. It does
however recreate the problem I've run into. This is stripped-down code
from a much more meaningful system.

I have two example classes, "AutoChecker" and "Snapshot" that evaluate
variables in their caller's namespace using the frame stack. As
written, the output is not what is expected: the variables evaluate to
"stagnant" values.

However, if the one indicated line is uncommented, then the result is
as expected.

So my questions are: Is this a bug in Python? Is this an invalid use
of frame data? Why does the single line "sys._getframe(1).f_locals"
fix the behavior?

Thanks,

Mike


import sys

class Snapshot(object):
def __init__(self, caller_globals, caller_locals):
self.signals = []
self.caller_globals = caller_globals
self.caller_locals = caller_locals

def get_values(self):
samples = {}
for signal in self.signals:
samples[signal] = eval(signal, self.caller_globals,
self.caller_locals)
return samples

def print_values(self):
print 'snapshot data'
for name, value in self.get_values().items():
print '\t', name, '=', value


class AutoChecker(object):
def __init__(self, statement):
self.statement = statement
self.caller_globals = sys._getframe(1).f_globals
self.caller_locals = sys._getframe(1).f_locals
self.snapshot = Snapshot(self.caller_globals,
self.caller_locals)
self.snapshot_history = []

def check(self):
# uncomment following line to get expected behavior
#sys._getframe(1).f_locals
if eval(self.statement, self.caller_globals,
self.caller_locals) == False:
print self.statement, 'failed'
self.snapshot.print_values()
self.snapshot_history.append(self.snapshot.get_val ues())

def report(self):
if len(self.snapshot_history):
return
print 'snapshot history'
for samples in self.snapshot_history:
for name, value in samples.items():
print '\t', name, '=', value


def f():
x = 0.0
y = 0.0
ac1 = AutoChecker('x < 2.0')
ac1.snapshot.signals.append('x')
ac1.snapshot.signals.append('y')

for i in range(5):
x = i / 2.0
y = x / 2
print i, x
ac1.check()
ac1.snapshot.print_values()
ac1.report()
 
Reply With Quote
 
 
 
 
Peter Otten
Guest
Posts: n/a
 
      11-15-2009
Mike wrote:

> I'll apologize first for this somewhat lengthy example. It does
> however recreate the problem I've run into. This is stripped-down code
> from a much more meaningful system.
>
> I have two example classes, "AutoChecker" and "Snapshot" that evaluate
> variables in their caller's namespace using the frame stack. As
> written, the output is not what is expected: the variables evaluate to
> "stagnant" values.
>
> However, if the one indicated line is uncommented, then the result is
> as expected.
>
> So my questions are: Is this a bug in Python? Is this an invalid use
> of frame data? Why does the single line "sys._getframe(1).f_locals"
> fix the behavior?


A simplified demonstration of your problem:

>>> def f(update):

.... a = locals()
.... x = 42
.... if update: locals()
.... print a
....
>>> f(False)

{'update': False}
>>> f(True)

{'a': {...}, 'x': 42, 'update': True}

The local namespace is not a dictionary, and the locals()/f_locals
dictionary contains a snapshot of the local namespace. Accessing the
f_locals attribute is one way to trigger an update of that snapshot.

What's puzzling is that the same dictionary is reused.

Peter

 
Reply With Quote
 
 
 
 
exarkun@twistedmatrix.com
Guest
Posts: n/a
 
      11-15-2009
On 04:00 pm, http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
>Mike wrote:
>>I'll apologize first for this somewhat lengthy example. It does
>>however recreate the problem I've run into. This is stripped-down code
>>from a much more meaningful system.
>>
>>I have two example classes, "AutoChecker" and "Snapshot" that evaluate
>>variables in their caller's namespace using the frame stack. As
>>written, the output is not what is expected: the variables evaluate to
>>"stagnant" values.
>>
>>However, if the one indicated line is uncommented, then the result is
>>as expected.
>>
>>So my questions are: Is this a bug in Python? Is this an invalid use
>>of frame data? Why does the single line "sys._getframe(1).f_locals"
>>fix the behavior?

>
>A simplified demonstration of your problem:
>>>>def f(update):

>... a = locals()
>... x = 42
>... if update: locals()
>... print a
>...
>>>>f(False)

>{'update': False}
>>>>f(True)

>{'a': {...}, 'x': 42, 'update': True}
>
>The local namespace is not a dictionary, and the locals()/f_locals
>dictionary contains a snapshot of the local namespace. Accessing the
>f_locals attribute is one way to trigger an update of that snapshot.
>
>What's puzzling is that the same dictionary is reused.


http://bugs.python.org/issue6116 is vaguely related.

Jean-Paul
 
Reply With Quote
 
Terry Reedy
Guest
Posts: n/a
 
      11-15-2009
Peter Otten wrote:
> Mike wrote:
>
>> I'll apologize first for this somewhat lengthy example. It does
>> however recreate the problem I've run into. This is stripped-down code
>> from a much more meaningful system.
>>
>> I have two example classes, "AutoChecker" and "Snapshot" that evaluate
>> variables in their caller's namespace using the frame stack. As
>> written, the output is not what is expected: the variables evaluate to
>> "stagnant" values.
>>
>> However, if the one indicated line is uncommented, then the result is
>> as expected.
>>
>> So my questions are: Is this a bug in Python?


No. The existence and use of sys._getframe -- notice the leading
underscore -- is a CPython implementation artifact. Use at your own risk.

>> Is this an invalid use of frame data?


Up to you to decide.

>> Why does the single line "sys._getframe(1).f_locals"
>> fix the behavior?


It updates the dictionary.

> A simplified demonstration of your problem:
>
>>>> def f(update):

> ... a = locals()
> ... x = 42
> ... if update: locals()
> ... print a
> ...
>>>> f(False)

> {'update': False}
>>>> f(True)

> {'a': {...}, 'x': 42, 'update': True}
>
> The local namespace is not a dictionary, and the locals()/f_locals
> dictionary contains a snapshot of the local namespace. Accessing the
> f_locals attribute is one way to trigger an update of that snapshot.
>
> What's puzzling is that the same dictionary is reused.


Efficiency? Consistency? The doc for locals says "locals()
Update and return a dictionary representing the current local symbol
table." In class statements, where (currently) the local namespace *is*
a dict, no update is needed and locals() simply returns the dict, the
same one each time.

Terry Jan Reedy


 
Reply With Quote
 
Mike
Guest
Posts: n/a
 
      11-18-2009
On Nov 15, 1:36*pm, Terry Reedy <(E-Mail Removed)> wrote:
> Peter Otten wrote:
> > Mike wrote:

>
> >> I'll apologize first for this somewhat lengthy example. It does
> >> however recreate the problem I've run into. This is stripped-down code
> >> from a much more meaningful system.

>
> >> I have two example classes, "AutoChecker" and "Snapshot" that evaluate
> >> variables in their caller's namespace using the frame stack. As
> >> written, the output is not what is expected: the variables evaluate to
> >> "stagnant" values.

>
> >> However, if the one indicated line is uncommented, then the result is
> >> as expected.

>
> >> So my questions are: Is this a bug in Python?

>
> No. The existence and use of sys._getframe -- notice the leading
> underscore -- is a CPython implementation artifact. Use at your own risk.
>
> *>> Is this an invalid use of frame data?
>
> Up to you to decide.
>
> *>> Why does the single line "sys._getframe(1).f_locals"
>
> >> fix the behavior?

>
> It updates the dictionary.
>
>
>
> > A simplified demonstration of your problem:

>
> >>>> def f(update):

> > ... * * a = locals()
> > ... * * x = 42
> > ... * * if update: locals()
> > ... * * print a
> > ...
> >>>> f(False)

> > {'update': False}
> >>>> f(True)

> > {'a': {...}, 'x': 42, 'update': True}

>
> > The local namespace is not a dictionary, and the locals()/f_locals
> > dictionary contains a snapshot of the local namespace. Accessing the
> > f_locals attribute is one way to trigger an update of that snapshot.

>
> > What's puzzling is that the same dictionary is reused.

>
> Efficiency? Consistency? The doc for locals says "locals()
> Update and return a dictionary representing the current local symbol
> table." In class statements, where (currently) the local namespace *is*
> a dict, no update is needed and locals() simply returns the dict, the
> same one each time.
>
> Terry Jan Reedy


Thanks for the replies.

If Peter's concise and much-appreciated example were to be modified as
such:

>>> def f(update):

.....: a = inspect.stack()[0][0].f_locals
.....: x = 42
.....: if update:
.....: inspect.stack()[0][0].f_locals
.....: print a
.....:
>>> f(False)

{'update': False}
>>> f(True)

{'a': {...}, 'x': 42, 'update': True}

Now there's no use of locals() to perform its documented "Update", but
just a simple access of a dictionary. This behavior is curious.

Further modification by accessing 'a' instead of '...f_locals' upon
update produces:

>>> f(False)

{'update': False}
>>> f(True)

{'update': True}

Checking the id() of 'a' and '...f_locals' shows the same "address".

How is it that '...f_locals' gets updated in this example? Is it done
in "stack()"?

Where exactly is the frame data stored prior to updating the
dictionary and can I get to it?

Thanks,
Mike
 
Reply With Quote
 
Mike
Guest
Posts: n/a
 
      11-18-2009
On Nov 15, 1:36*pm, Terry Reedy <(E-Mail Removed)> wrote:
> Peter Otten wrote:
> > Mike wrote:

>
> >> I'll apologize first for this somewhat lengthy example. It does
> >> however recreate the problem I've run into. This is stripped-down code
> >> from a much more meaningful system.

>
> >> I have two example classes, "AutoChecker" and "Snapshot" that evaluate
> >> variables in their caller's namespace using the frame stack. As
> >> written, the output is not what is expected: the variables evaluate to
> >> "stagnant" values.

>
> >> However, if the one indicated line is uncommented, then the result is
> >> as expected.

>
> >> So my questions are: Is this a bug in Python?

>
> No. The existence and use of sys._getframe -- notice the leading
> underscore -- is a CPython implementation artifact. Use at your own risk.
>
> *>> Is this an invalid use of frame data?
>
> Up to you to decide.
>
> *>> Why does the single line "sys._getframe(1).f_locals"
>
> >> fix the behavior?

>
> It updates the dictionary.
>
>
>
> > A simplified demonstration of your problem:

>
> >>>> def f(update):

> > ... * * a = locals()
> > ... * * x = 42
> > ... * * if update: locals()
> > ... * * print a
> > ...
> >>>> f(False)

> > {'update': False}
> >>>> f(True)

> > {'a': {...}, 'x': 42, 'update': True}

>
> > The local namespace is not a dictionary, and the locals()/f_locals
> > dictionary contains a snapshot of the local namespace. Accessing the
> > f_locals attribute is one way to trigger an update of that snapshot.

>
> > What's puzzling is that the same dictionary is reused.

>
> Efficiency? Consistency? The doc for locals says "locals()
> Update and return a dictionary representing the current local symbol
> table." In class statements, where (currently) the local namespace *is*
> a dict, no update is needed and locals() simply returns the dict, the
> same one each time.
>
> Terry Jan Reedy


Thanks for the replies.

If Peter's concise and much-appreciated example were to be modified as
such:

>>> def f(update):

.....: a = inspect.stack()[0][0].f_locals
.....: x = 42
.....: if update:
.....: inspect.stack()[0][0].f_locals
.....: print a
.....:
>>> f(False)

{'update': False}
>>> f(True)

{'a': {...}, 'x': 42, 'update': True}

Now there's no use of locals() to perform its documented "Update", but
just a simple access of a dictionary. This behavior is curious.

Further modification by accessing 'a' instead of '...f_locals' upon
update produces:

>>> f(False)

{'update': False}
>>> f(True)

{'update': True}

Checking the id() of 'a' and '...f_locals' shows the same "address".

How is it that '...f_locals' gets updated in this example? Is it done
in "stack()"?

Where exactly is the frame data stored prior to updating the
dictionary and can I get to it?

Thanks,
Mike
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: Linux usage stagnant or dropping? peterwn NZ Computing 2 03-03-2010 12:58 AM
Server.Transfer - frame to non frame jason ASP .Net 1 09-05-2005 07:34 AM
Framesets - Event in frame 'A' triggering update of frame 'B' -How ? JAW ASP .Net 2 11-09-2004 07:54 PM
Referring to a frame's content from another frame Microsoft ASP .Net 3 10-04-2004 06:35 AM
Manipulating control in one frame from another frame, how? Søren M. Olesen ASP .Net 0 11-13-2003 05:37 PM



Advertisments