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.