为什么在函数中使用模块后重新导入会引发异常



我在这里使用 python2.7:

import time
def foo():
    print time.time()  # EXCEPTION THROWN HERE
    import time

。引发异常:

UnboundLocalError: local variable 'time' referenced before assignment

如果我删除重新导入:

import time
def foo():
    print time.time()  # WORKS AS EXPECTED
    #import time

。一切都按预期进行。很明显,当调用函数时,有关后续导入的某些内容会影响局部变量表,从函数开始执行的那一刻起 - 而不是从包含点开始:

import time
def foo():
    global time
    print time.time()  # WORKS AS EXPECTED
    import time

。奇怪。

出现这种情况是因为工程师在一个大型方法的顶部添加了对 time.time() 的调用,但没有看到它在函数中间导入(由一位早已离开的工程师导入)。我不是在寻求有关如何解决问题的指导 - 这是可悲的显而易见的(并且还将涉及追捕这样做的人,提供必要的毒品耳光。

我很好奇这个机制,为什么这样做,以及我可以检查系统的哪些部分来查看它的所有运行情况。

问题与import无关。它只是关于全局变量与局部变量。请参阅此最小示例:

x = 0
def access():
    print(x)
def shadow():
    print(x)
    x = 1

现在让我们拆解函数并看一下字节码:

access()

 0 LOAD_GLOBAL              0 (print)
 3 LOAD_GLOBAL              1 (x)
 6 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
 9 POP_TOP
10 LOAD_CONST               0 (None)
13 RETURN_VALUE

您可以看到符号x被查找为全局变量LOAD_GLOBAL 1 (x)

shadow()

 0 LOAD_GLOBAL              0 (print)
 3 LOAD_FAST                0 (x)
 6 CALL_FUNCTION            1 (1 positional, 0 keyword pair)
 9 POP_TOP
10 LOAD_CONST               1 (1)
13 STORE_FAST               0 (x)
16 LOAD_CONST               0 (None)
19 RETURN_VALUE

当您在函数体中重新定义变量x时,我们得到的是这个字节码:LOAD_FAST 0 (x) 。因此,即使此时尚未定义,它也会作为局部变量进行查找。由于没有定义局部变量x但我们得到了UnboundLocalError,即未定义的局部变量。

在您的示例中,模块time是全局/局部变量。

相关内容

  • 没有找到相关文章

最新更新