I was confident to have at least some basic understanding of Python's scope system. Now I get an error and unfortunately I'm not even able to write a good code snippet for reproduction so far. I tried to reproduce it in a new small project, but everything works as I expect there :-/
I can only describe what I do and hopefully somebody detects a pattern and can tell me what possibly goes wrong here.
At first there is a python file x.py
which implements a class X
.
In some other python file, there is the following string:
code="""
...
from x import X
...
class Y(X): # does not crash here, ...
def __init__(self):
X.__init__(self) # ... but here
...
foo=Y()
"""
You can assume that python is able to find the x
module. At some place, I try to execute that:
exec(code, globals(), locals())
And now I get the NameError
. It tells me that X
is not defined when it tries to call it's constructor. It was obviously defined a few lines above.
If I modify Y.__init__
with adding from x import X
as first line, it works. But why the hell do I have to import it again there?
As already indicated, the actual code is more complex and does more things. In an unlucky case, my posting does not even show the part which actually leads to the problem. But maybe you have some general ideas, how one can get such a behaviour.
This is just a guess, because you haven't shown us enough code, and what you've shown us doesn't actually reproduce the problem, but…
If you're doing this exec
inside a function, then locals()
and globals()
are going to be different. In which case the code will be executed as if it were inside a class definition. So, it'll be (sort of) as if you did this:
class _:
from x import X
class Y(X): # does not crash here, ...
def __init__(self):
X.__init__(self) # ... but here
foo=Y()
del _
(I previously thought you'd have to also be doing something like Y()
outside the exec
, but user2357112's answer convinced me that isn't necessary.)
If that's your problem, you may be able to fix it by just calling exec(code, globals(), globals())
or exec(code, locals(), locals())
. (Which one is appropriate, if either, depends on what you're actually trying to do, of course, which you haven't told us.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With