You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
"RuntimeWarning: assigning None to unbound local": an inscrutable error #124118
RuntimeWarning: assigning None to unbound local ← I get this periodically since upgrading to python 3.12, for various lines of library code somewhere deep in my project's dependencies, and it seems like there's no documentation for it online? It's not even clear to me from the error message why this would be a bad thing to happen. These warnings generally seem to show up in list comprehensions. I don't know how to fix them or what they indicate. Maybe it's even a bug in python! I'm using Python 3.12.6 on Windows 10.
RuntimeWarning: assigning None to unbound local ← I get this periodically since upgrading to python 3.12, for various lines of library code somewhere deep in my project's dependencies, and it seems like there's no documentation for it online? It's not even clear to me from the error message why this would be a bad thing to happen. These warnings generally seem to show up in list comprehensions. I don't know how to fix them or what they indicate. Maybe it's even a bug in python! I'm using Python 3.12.6 on Windows 10.
I would like to, but I don't really know where in the program it comes from, nor do I have an minimal repro.
Can you run the code on your machine?
import ast
expr_class_names = ({n for n, c in ast.__dict__.items()
if isinstance(c, type) and issubclass(c, ast.expr)} |
{'AssignName', 'DelName', 'Const', 'AssignAttr', 'DelAttr'})
print(expr_class_names)
This error is from here in _PyFrame_LocalsToFast. It was added in #99075 (cc @brandtbucher). In 3.13 this check is gone again, so it's only in 3.12.
I'm not very familiar with this code, but it seems to interact with code paths that only trigger if you have a trace function enabled. For example, Brandt added a unit test that triggers this warning by doing del frame.f_locals["x"] in a trace function. Are you running with any trace function?
I was able to reproduce this with just Python 3.12 (but only in the REPL for some reason, not when I put the same code in a file):
% python3.12
Python 3.12.5 (main, Aug 6 2024, 19:08:49) [Clang 15.0.0 (clang-1500.3.9.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def trace(frame, event, arg):
... if "s" in frame.f_locals:
... del frame.f_locals["s"]
... return trace
...
>>> import sys
>>> sys.settrace(trace)
>>> [s for s in dir() if s]
<stdin>:1: RuntimeWarning: assigning None to unbound local 's'
However, if you have a trace function that deletes locals, it seems reasonable that we raise warnings. I'd be curious what is causing the issue in the OP's code.
Did you attach any debugger when you run this code? How did you run the code?
This warning happens when you try to write/delete a local variable in a trace function. The reason @JelleZijlstra's code only repros in REPL is because when [s for s in dir() if s] is in module-level, its f_locals will be a real dict same as f_globals. Changing it won't matter to the actual locals.
And yes, there are module level locals - hidden locals, introduced by PEP 709. They are basically comprehension locals when they are inlined (also in 3.12).
This may or may not be a bug in CPython. I still need more info to figure out what's the trigger. You can, probably, do something crazy in your debugger/trace function to trigger this, but this also could be a corner that's forgotten when implementing PEP 709.
Both cases listed are a global comprehension - they are comprehensions at module level so I can imagine there are some dark corners when trying to work with fast locals in module level.
This happens whether I'm in the repl or executing it from a file.
@picnixz I agree that it seems to me likely to be a problem in third-party packages. But today I had resolved to investigate those errors, and ran into the difficulty that the RuntimeWarning here isn't documented anywhere, leaving me at a bit of a loss.
@JelleZijlstra I was also able to reproduce using this code, but only in the repl, not when run from a file. I don't think I'm using a trace function directly, but come to think of it my code does use (an old version of) pyinstrument; so that might have a trace function. My code is also running inside of streamlit, which could also conceivably have a trace in it somewhere. I will try running it various ways...
Yep, OK, removing the profiler meant I couldn't get any of these errors, and adding the profiler back in made one happen. So I think it's safe to say it's my profiler. And, looking into it, it seems the author of the profiler noticed this problem and fixed it about 3 weeks ago!
So, not a bug in CPython. Perhaps the warning could use documentation somewhere... although, on the other hand, it seems like the actual author of the profiler was able to figure it out well enough.
The warning should not really happen for common users. This is some dark zone that users need to explore with their own flashlights. I'm glad the author of pyinstrument has figured it out. From the issue listed it seems like this is indeed a third party bug. So I'll close this one for now.
Reacted by wyattscarpenter, Kirill Podoprigora and Carl Meyer
Activity
rruuaanng commentedon Sep 16, 2024
Can you show the code that triggers the error?
wyattscarpenter commentedon Sep 16, 2024
I would like to, but I don't really know where in the program it comes from, nor do I have an minimal repro.
rruuaanng commentedon Sep 16, 2024
Oh, that's really sad.
rruuaanng commentedon Sep 16, 2024
Can you run the code on your machine?
Of course, Put the running results here.
picnixz commentedon Sep 16, 2024
JelleZijlstra commentedon Sep 16, 2024
This error is from here in
_PyFrame_LocalsToFast. It was added in #99075 (cc @brandtbucher). In 3.13 this check is gone again, so it's only in 3.12.I'm not very familiar with this code, but it seems to interact with code paths that only trigger if you have a trace function enabled. For example, Brandt added a unit test that triggers this warning by doing
del frame.f_locals["x"]in a trace function. Are you running with any trace function?I was able to reproduce this with just Python 3.12 (but only in the REPL for some reason, not when I put the same code in a file):
However, if you have a trace function that deletes locals, it seems reasonable that we raise warnings. I'd be curious what is causing the issue in the OP's code.
gaogaotiantian commentedon Sep 16, 2024
Did you attach any debugger when you run this code? How did you run the code?
This warning happens when you try to write/delete a local variable in a trace function. The reason @JelleZijlstra's code only repros in REPL is because when
[s for s in dir() if s]is in module-level, itsf_localswill be a real dict same asf_globals. Changing it won't matter to the actual locals.And yes, there are module level locals - hidden locals, introduced by PEP 709. They are basically comprehension locals when they are inlined (also in 3.12).
This may or may not be a bug in CPython. I still need more info to figure out what's the trigger. You can, probably, do something crazy in your debugger/trace function to trigger this, but this also could be a corner that's forgotten when implementing PEP 709.
Both cases listed are a global comprehension - they are comprehensions at module level so I can imagine there are some dark corners when trying to work with fast locals in module level.
Maybe @carljm has a better insight than I do.
wyattscarpenter commentedon Sep 16, 2024
@rruuaanng
I get this result, with no error:
{'Dict', 'YieldFrom', 'Starred', 'UnaryOp', 'NamedExpr', 'BoolOp', '_ast_Ellipsis', 'Constant', 'IfExp', 'Set', 'Await', 'Tuple', 'AssignAttr', 'Const', 'ListComp', 'DelName', 'DictComp', 'Yield', 'DelAttr', 'Name', 'SetComp', 'Subscript', 'BinOp', 'Call', 'FormattedValue', 'JoinedStr', 'Compare', 'expr', 'GeneratorExp', 'Lambda', 'Attribute', 'List', 'AssignName', 'Slice'}This happens whether I'm in the repl or executing it from a file.
@picnixz I agree that it seems to me likely to be a problem in third-party packages. But today I had resolved to investigate those errors, and ran into the difficulty that the RuntimeWarning here isn't documented anywhere, leaving me at a bit of a loss.
@JelleZijlstra I was also able to reproduce using this code, but only in the repl, not when run from a file. I don't think I'm using a trace function directly, but come to think of it my code does use (an old version of) pyinstrument; so that might have a trace function. My code is also running inside of streamlit, which could also conceivably have a trace in it somewhere. I will try running it various ways...
wyattscarpenter commentedon Sep 16, 2024
Yep, OK, removing the profiler meant I couldn't get any of these errors, and adding the profiler back in made one happen. So I think it's safe to say it's my profiler. And, looking into it, it seems the author of the profiler noticed this problem and fixed it about 3 weeks ago!
wyattscarpenter commentedon Sep 16, 2024
So, not a bug in CPython. Perhaps the warning could use documentation somewhere... although, on the other hand, it seems like the actual author of the profiler was able to figure it out well enough.
gaogaotiantian commentedon Sep 16, 2024
The warning should not really happen for common users. This is some dark zone that users need to explore with their own flashlights. I'm glad the author of
pyinstrumenthas figured it out. From the issue listed it seems like this is indeed a third party bug. So I'll close this one for now.wyattscarpenter commentedon Sep 16, 2024
Thanks everyone!
bump pyinstrument to v5.0.1