为什么flake8为我在`as`块中定义的内容说“未定义名称”?

时间:2020-06-24 09:08:03

标签: python flake8

考虑以下示例:

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抱怨?该代码似乎可以正常运行。

1 个答案:

答案 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的维护者之一