为什么在函数中使用模块后重新导入会抛出异常?
Why does RE-importing after a module is used in a function throw an exception?
我在欺骗 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
...一切正常。很明显,当调用该函数时,从函数开始执行的那一刻起,有关稍后导入的某些内容会影响局部变量 table,而不是从包含点开始:
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
aka local variable not defined.
在您的示例中,模块 time
是 global/local 变量。
我在欺骗 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
...一切正常。很明显,当调用该函数时,从函数开始执行的那一刻起,有关稍后导入的某些内容会影响局部变量 table,而不是从包含点开始:
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
aka local variable not defined.
在您的示例中,模块 time
是 global/local 变量。