函数内部的python导入隐藏了现有变量

时间:2014-06-19 12:59:31

标签: python python-import

我正在与一个奇怪的" 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语句会隐藏函数作用域中已存在的同名变量,即使未执行导入也是如此。

这感觉反直觉和非pythonic。我试图找到一些关于此的信息或文档,到目前为止没有取得多大成功。有关于此行为的更多信息/见解吗?

感谢

2 个答案:

答案 0 :(得分:3)

你遇到的问题只是对同一个问题的重述。方式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是本地的。

答案 1 :(得分:1)

通过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'>}