Python版本之间的可变范围差异

时间:2019-04-24 15:00:27

标签: python

请考虑以下代码:

import shutil
import time
t = time.time()
exception = None
while time.time() < (t + 10.0):
    try:
        shutil.rmtree('/path-to-non-existent-directory')
        break
    except OSError as exception:
        pass
    time.sleep(0.1)
else:
    if exception:
        raise exception

在Python 2.7中,此代码完全有效,但在Python 3.7中,我收到以下警告:

Local variable exception might be referenced before assignment

else子句中。

有人知道在Python 3.7中运行时此代码段有什么问题吗?

2 个答案:

答案 0 :(得分:1)

在Python 3中,为解决由于引入__traceback__属性而引起的循环引用问题,在except块的末尾会自动删除一个except目标。就像您写过一样

except OSError as exception:
    pass
    del exception

这在PEP 3110中有记录。

如果要保留异常对象,则应将其保存到第二个变量:

except OSError as exception:
    saved_exception = exception

exception仍将被删除,但是在saved_exception块结束之后,您可以使用except检查异常对象。

答案 1 :(得分:0)

Python是一种块作用域语言,您不能在定义它的块之外引用变量,也不能在更新了该变量的块之外使用新值。

换句话说,您不能在exception块之外引用except变量的错误数据,如果尝试这样做,则exception变量的值将是None(在顶层设置)。

尝试将else块的内容移动到except块,并摆脱exception = Noneif exception,就像这样:

timer = Timer(10.0)
while timer.alive:
  try:
    shutil.rmtree(cls.workspace)
    break
  except OSError as exception:
    raise exception
  time.sleep(0.1)

如果您不希望出现致命错误,则可以使用print()函数而不是raise关键字:

timer = Timer(10.0)
while timer.alive:
  try:
    shutil.rmtree(cls.workspace)
    break
  except OSError as exception:
    print(exception)
  time.sleep(0.1)

这是另一个示例(不起作用):

def hello():
  message = "Hello World"

print(message)

因为它会引发以下错误:

NameError: name 'message' is not defined

注意::建议不要调用您的异常exception,因为有一个名为Exception的错误类,这样做以后可能会引起混乱。

祝你好运。