Python globals, locals, and UnboundLocalError

cdleary picture cdleary · Jan 1, 2009 · Viewed 7.4k times · Source

I ran across this case of UnboundLocalError recently, which seems strange:

import pprint

def main():
    if 'pprint' in globals(): print 'pprint is in globals()'
    pprint.pprint('Spam')
    from pprint import pprint
    pprint('Eggs')

if __name__ == '__main__': main()

Which produces:

pprint is in globals()
Traceback (most recent call last):
  File "weird.py", line 9, in <module>
    if __name__ == '__main__': main()
  File "weird.py", line 5, in main
    pprint.pprint('Spam')
UnboundLocalError: local variable 'pprint' referenced before assignment

pprint is clearly bound in globals, and is going to be bound in locals in the following statement. Can someone offer an explanation of why it isn't happy resolving pprint to the binding in globals here?

Edit: Thanks to the good responses I can clarify my question with relevant terminology:

At compile time the identifier pprint is marked as local to the frame. Does the execution model have no distinction where within the frame the local identifier is bound? Can it say, "refer to the global binding up until this bytecode instruction, at which point it has been rebound to a local binding," or does the execution model not account for this?

Answer

Albert Visser picture Albert Visser · Jan 1, 2009

Where's the surprise? Any variable global to a scope that you reassign within that scope is marked local to that scope by the compiler.

If imports would be handled differently, that would be surprising imho.

It may make a case for not naming modules after symbols used therein, or vice versa, though.