在函数内部导入Python会隐藏现有变量

2022-03-31 00:00:00 python python-import

问题描述

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

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

它的输出是这样的(我尝试了python2.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 foo

的(大致)语法糖
foo = __import__("foo")

因此,您的代码为:

x = 1
def bar():
    print x
    if False:
        x = 2

由于名称logging出现在BAR内赋值语句的左侧,因此它被视为局部变量引用,因此,即使设置它的行永远不能被调用,也不会在该作用域中查找同名的全局变量。

处理全局变量的常见解决方法适用:使用您已经发现的其他名称,或者:

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

以便Python不会认为logging是本地的。

相关文章