'NameError: global name not defined' in pdb, for a dictionary that exists

I ran into re-scope problem in lambda function. I can successfully print foo to stdout, but I get an error when using max() , including lambda - see the simplified code below ...

In general, I am trying to find the highest value for the nested budget key within an unknown number of first order keys.

 (Pdb) foo = self.some_method() # some_method() returns a dict, printed in the next step (Pdb) pp foo {'1': {'count': 1, 'extra_data': {'activity-count': 1, 'budget': 0, [...MORE KEY-VALUE PAIRS HERE...] 'version': 1}, [...LOTS MORE KEY-VALUE PAIRS HERE...] 'elements_total': defaultdict(<type 'int'>, {'result': 1, 'another_key': 2}), 'extra_year_data': defaultdict(<function <lambda> at 0x10e05bd70>, {})}, '2': {'count': 1, 'extra_data': {'activity-count': 1, 'budget': 3, [...MORE KEY-VALUE PAIRS HERE...] 'version': 1}, [...LOTS MORE KEY-VALUE PAIRS HERE...] 'elements_total': defaultdict(<type 'int'>, {'result': 1, 'another_key': 2}), 'extra_year_data': defaultdict(<function <lambda> at 0x10e05bd70>, {})}} (Pdb) max(foo, key=lambda x: foo[x]['extra_data']['budget']) *** NameError: global name 'foo' is not defined 

In general, I am trying to use max(foo, key=lambda x: foo[x]['extra_data']['budget']) to find the highest value for the nested budget key within an unknown number of first-order keys.

The expected result in this case may be 2 as the value for foo['2']['extra_data']['budget'] = 3 vs. foo['1']['extra_data']['budget'] = 0 .

Could the error be due to the fact that some of the (unrelated) keys have a defaultdict inside them?

+2
python lambda nameerror pdb
source share
2 answers

You set a new local one with pdb , but this is not visible to expressions using nested areas in this debugger session. Any expression in a nested region, such as lambda , used for the key argument, using a name that is local to the current frame should be a close and will have this problem.

This is a limitation of how the debugger and compilation of Python work; closing can only be created if the function that should produce them was compiled in the same session. Since the function you are debugging was compiled without foo being a closure, it cannot be used by the lambda expression as such.

You can bind a locale to a lambda (making it local rather than closing):

 max(foo, key=lambda x, foo=foo: foo[x]['extra_data']['budget']) 

See What exactly is contained in obj .__ clos__? for more information on how the Python compiler creates closures.

+7
source share

There is a bug report for Python 3 (however this issue affects Python 2.7, and also you found out) that offers Martijn as an alternative: interact at the pdb prompt takes you to an interactive session filled with globals() and locals() and your lambda should work as expected.

+1
source share

All Articles