By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,270 Members | 1,703 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,270 IT Pros & Developers. It's quick & easy.

exec src in {}, {} strangeness

P: n/a
hi there,

I have trouble running some python code with 'exec':

t.py contains:
class Foo: pass
class Bar:
f = Foo

From a python shell I do:
f = ''.join(open('t.py').readlines())
exec f in {}, {}

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<string>", line 2, in ?
File "<string>", line 3, in Bar
NameError: name 'Foo' is not defined
However, when I use the current global and local scope, i.e.
simply 'exec f', everything works fine. What am I missing ?

Thanks,
Stefan
Jul 18 '05 #1
Share this Question
Share on Google+
8 Replies


P: n/a
Hi !
Try :

exec f in globals(),locals()
or
exec(f,globals(),locals())
or
exec f in globals(),globals()
or
exec(f,globals(),globals())

@-salutations

Michel Claveau
Jul 18 '05 #2

P: n/a
Do Re Mi chel La Si Do wrote:
Hi !
Try :

exec f in globals(),locals()
or
exec(f,globals(),locals())
or
exec f in globals(),globals()
or
exec(f,globals(),globals())


Indeed, using 'globals()' and 'locals()' works. However,
both report the same underlaying object, which is a bit
confusing. (Under what circumstances does 'locals()' return
not the same object as 'globals()' ?)

The problem appears to be that

exec f in a, b

where a and b are distinct dictionaries, does not look up
symbols in 'a' when in local scope.
I filed a bug report (#1167300).

Regards,
Stefan
Jul 18 '05 #3

P: n/a
Stefan Seefeld wrote:
Indeed, using 'globals()' and 'locals()' works. However,
both report the same underlaying object, which is a bit
confusing. (Under what circumstances does 'locals()' return
not the same object as 'globals()' ?)


When you aren't at the interactive prompt... there are
no "locals" there, so locals() just maps through to globals().
(Probably this applies to all code at the module level,
as oppsed to code inside any callable, but I haven't
verified... you can easily enough.)

Does this information invalidate your bug report?

-Peter
Jul 18 '05 #4

P: n/a
Peter Hansen wrote:
Stefan Seefeld wrote:
Indeed, using 'globals()' and 'locals()' works. However,
both report the same underlaying object, which is a bit
confusing. (Under what circumstances does 'locals()' return
not the same object as 'globals()' ?)

When you aren't at the interactive prompt... there are
no "locals" there, so locals() just maps through to globals().
(Probably this applies to all code at the module level,
as oppsed to code inside any callable, but I haven't
verified... you can easily enough.)

Does this information invalidate your bug report?


No, but that's possibly only because I don't (yet) understand
the implications of what you are saying.

Is there anything wrong with 'exec source in a, b' where
a and b are distinc originally empty dictionaries ? Again,
my test code was

class Foo: pass
class Bar:
foo = Foo

and it appears as if 'Foo' was added to 'a', but when evaluating
'foo = Foo' the interpreter only looked in 'b', not 'a'.

Thanks,
Stefan
Jul 18 '05 #5

P: n/a
Stefan Seefeld <se*****@sympatico.ca> writes:
Is there anything wrong with 'exec source in a, b' where
a and b are distinc originally empty dictionaries ? Again,
my test code was

class Foo: pass
class Bar:
foo = Foo

and it appears as if 'Foo' was added to 'a', but when evaluating
'foo = Foo' the interpreter only looked in 'b', not 'a'.


No, it's the other way round. Foo is added in b since bindings are done
in the local scope. Your case is a bit more complicated, though.
Here's what I think happens:

class Foo is bound in b, the locals dictionary, so there is no reference
to Foo in the globals dictionary. The body of class B is executed with
it's own new locals dictionary. That locals dictionary will effectively
be turned into Bar.__dict__ when the class object is created.

When "foo = Foo" is executed, Foo is first looked up in that new locals
dictionary. That fails, so it's also looked up in the globals
dictionary a. That fails as well because Foo was bound in b. The final
lookup in the builtins also fails, and thus you get an exception.
Bernhard

--
Intevation GmbH http://intevation.de/
Skencil http://skencil.org/
Thuban http://thuban.intevation.org/
Jul 18 '05 #6

P: n/a
Bernhard Herzog wrote:
Stefan Seefeld <se*****@sympatico.ca> writes:

Is there anything wrong with 'exec source in a, b' where
a and b are distinc originally empty dictionaries ? Again,
my test code was

class Foo: pass
class Bar:
foo = Foo

and it appears as if 'Foo' was added to 'a', but when evaluating
'foo = Foo' the interpreter only looked in 'b', not 'a'.

No, it's the other way round. Foo is added in b since bindings are done
in the local scope. Your case is a bit more complicated, though.
Here's what I think happens:

class Foo is bound in b, the locals dictionary, so there is no reference
to Foo in the globals dictionary. The body of class B is executed with
it's own new locals dictionary. That locals dictionary will effectively
be turned into Bar.__dict__ when the class object is created.

When "foo = Foo" is executed, Foo is first looked up in that new locals
dictionary. That fails, so it's also looked up in the globals
dictionary a. That fails as well because Foo was bound in b. The final
lookup in the builtins also fails, and thus you get an exception.


Thanks for the explanation ! I'm still unable to make a conclusion:
What is wrong ? Am I doing something stupid (I did try various things
such as inserting __builtin__ into the dictionary, etc.) ?
Or is that really a bug ?

Thanks,
Stefan
Jul 18 '05 #7

P: n/a
Stefan Seefeld wrote:
Bernhard Herzog wrote:
When "foo = Foo" is executed, Foo is first looked up in that new locals
dictionary. That fails, so it's also looked up in the globals
dictionary a. That fails as well because Foo was bound in b. The final
lookup in the builtins also fails, and thus you get an exception.

Yes, from the experiment I just did, that does seem to
be what is happening.
Thanks for the explanation ! I'm still unable to make a conclusion:
What is wrong ? Am I doing something stupid...? Or is that really a bug?


It seems to be a hangover from the old two-scope system
where local scopes didn't nest. It probably qualifies as
a bug, since it differs from the modern behaviour of
a class definition inside the local scope of a function.

However, if your intention is to define the classes in
the global dict then yes, you are doing something wrong --
you should be passing the same dictionary for both scopes:

g = {}
exec stuff_to_define in g, g
# definitions are now in g

--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg
Jul 18 '05 #8

P: n/a
As Greg pointed..

g = {}
exec open('t.py').read() in g, g

is what you want.

But you can write it also this way:
exec open('t.py').read() in {}

because if you specify only globals, the same
dictionary is also used for locals. (locals() is
used as a default only if you don't specify globals)

OR

explicitly move class Foo to globals

t.py contains:
globals Foo
class Foo: pass
class Bar:
f = Foo

(Should work. I haven't tried it, though)

BranoZ

Jul 18 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.