I was wrestling with a weird "UnboundLocalError: local variable referenced before assignment" issue in a multi-submodule project I am working on and slimmed it down to this snippet (using the logging module from standard library):
import logging
def foo():
logging.info('foo')
def bar():
logging.info('bar')
if False:
import logging.handlers
# With these alternatives things work:
# import logging.handlers as logginghandlers
# from logging.handlers import SocketHandler
logging.basicConfig(level=logging.INFO)
foo()
bar()
Which has this output (I tried python 2.7 and 3.3):
INFO:root:foo
Traceback (most recent call last):
File "import-test01.py", line 16, in <module>
bar()
File "import-test01.py", line 7, in bar
logging.info('bar')
UnboundLocalError: local variable 'logging' referenced before assignment
Apparently the presence of an import statement inside a function hides already existing variables with the same name in the function scope, even if the import is not executed.
This feels counter-intuitive and non-pythonic. I tried to find some information or documentation about this, without much success thus far. Has someone more information/insights about this behaviour?
thanks
The problem you're having is just a restatement of the same ol' way python deals with locals masking globals.
to understand it, import foo
is (approximately) syntactic sugar for:
foo = __import__("foo")
thus, your code is:
x = 1
def bar():
print x
if False:
x = 2
since the name logging
appears on the left side of an assignment statement inside bar, it is taken to be a local variable reference, and so python won't look for a global by the same name in that scope, even though the line that sets it can never be called.
The usual workarounds for dealing with globals apply: use another name, as you have found, or:
def bar():
global logging
logging.info('bar')
if False:
import logging.handlers
so that python won't think logging
is local.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With