Python import inside function隐藏现有变量



我在一个多子模块项目中遇到了一个奇怪的"UnboundLocalError:赋值前引用的局部变量"问题,并将其精简为以下代码片段(使用标准库中的日志模块):

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()

有这样的输出(我尝试了python 2.7和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

很明显,在函数中存在import语句隐藏了函数作用域中已经存在的同名变量,即使没有执行import。

这感觉是反直觉和非python的。我试图找到一些关于这方面的信息或文档,但迄今为止没有取得多大成功。有人对这种行为有更多的信息/见解吗?

谢谢

你遇到的问题只是python处理局部变量掩盖全局变量的老方法的一个重述。

为了理解

import foo(近似)是以下语法糖:

foo = __import__("foo")
因此,你的代码是:
x = 1
def bar():
    print x
    if False:
        x = 2

由于名称logging出现在赋值语句的左侧,因此它被认为是一个局部变量引用,因此python不会在该范围内查找同名的全局变量,即使设置它的行永远不能被调用。

处理全局变量的常用解决方法是:使用另一个名称,正如您所发现的,或者:

def bar():
    global logging
    logging.info('bar')
    if False:
        import logging.handlers

使python不会认为logging是本地的

通过import语句,您在函数中引入logging作为局部变量,并且在初始化之前调用该局部变量。

def bar():
    import logging.handlers
    print locals()
>>> foo()
{'logging': <module 'logging' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/logging/__init__.pyc'>}

最新更新