简体   繁体   中英

Why does flake8 say “undefined name” for something I defined in an `as` block?

Consider this example:

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))

And the flake8 output:

a.py:11:1: F841 local variable 'e' is assigned to but never used
a.py:13:28: F821 undefined name 'e'

Why does flake8 complain? The code seems to run properly.

As of python 3 an except: block only defines the name during the block itself

You can think of

try:
   ...  # 1
except Exception as e:
   ...  # 2

as the following:

try:
    ...  # 1
except Exception as e:
    try:
        ...  # 2
    finally:
        del e

For inner functions (including lambdas as is your example) in pyflakes (the tool which produces the F error codes), the evaluation of names is deferred until the end of the function. This is to handle cases like this:

def f():
    def g():
        print(x)  # it looks like `x` doesn't exist yet from a syntax perspective

   x = 1
   g()

and thirdly, pyflakes does not do any branch or context analysis for statements, you can ~kinda think of them all squished to the left without branches or blocks

so in your example, pyflakes roughly sees:

1/0
e = ...  # sys.exc_info()[1]
print('Caught')
do_something(lambda: f(e))
del e

and since at the end of the function e is del d, pyflakes treats it as ~potentially undefined. while it's obvious to a human that it is called in a place where it is defined, you'd need to solve the halting problem in practice to know that it is or isn't undefined (you'd ~essentially need to run the code or analyze every possible branch)

For the "issue" (though I believe it to be unsolvable) there's this in the tracker: https://github.com/PyCQA/pyflakes/issues/265


disclaimer: I am the current maintainer of flake8 and one of the maintainers of pyflakes

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM