考虑以下示例:
def f(*args, **kwargs):
print(*args, **kwargs)
def do_something(f):
f()
try:
1/0
except Exception as e:
print('Caught')
do_something(lambda: f(e))
和flake8输出:
a.py:11:1: F841 local variable 'e' is assigned to but never used
a.py:13:28: F821 undefined name 'e'
为什么flake8抱怨?该代码似乎可以正常运行。
答案 0 :(得分:1)
从python 3开始,except:
块仅在块本身中定义了名称
你会想到的
try:
... # 1
except Exception as e:
... # 2
如下:
try:
... # 1
except Exception as e:
try:
... # 2
finally:
del e
对于 pyflakes (产生F错误代码的工具)中的内部函数(包括lambdas,例如您的示例),名称的评估被推迟到函数结束。这是为了处理这样的情况:
def f():
def g():
print(x) # it looks like `x` doesn't exist yet from a syntax perspective
x = 1
g()
第三,pyflakes不对语句进行任何分支或上下文分析,您可以〜有点想起它们都被压缩到左侧而没有分支或块
因此在您的示例中,pyflakes大致看到:
1/0
e = ... # sys.exc_info()[1]
print('Caught')
do_something(lambda: f(e))
del e
,由于在函数e
的末尾是del
d,因此pyflakes将其视为潜在未定义的对象。虽然对于人类来说很明显,它在定义的地方被调用,但是您需要在实践中解决暂停问题,以了解它是否是未定义的(您基本上需要运行代码) 或分析每个可能的分支)
对于“问题”(尽管我认为这是无法解决的),跟踪器中有以下内容:https://github.com/PyCQA/pyflakes/issues/265
免责声明:我是flake8的当前维护者,也是pyflakes的维护者之一