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_values()) 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() -- http://mail.python.org/mailman/listinfo/python-list