Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > exec throws an exception...why?

Reply
Thread Tools

exec throws an exception...why?

 
 
Nick Jacobson
Guest
Posts: n/a
 
      06-06-2004
This works fine:

x = 1
def execfunc():
print x
execfunc()

So why doesn't this?

s = \
"""
x = 1
def execfunc():
print x
execfunc()
"""

codeobj = compile(s, "<string>", "exec")
d = {}
e = {}
exec codeobj in d, e

Error message:
Traceback (most recent call last):
File "C:\Nick\proj\python1.py", line 17, in ?
exec codeobj in d, e
File "<string>", line 6, in ?
File "<string>", line 5, in execfunc
NameError: global name 'x' is not defined

I'm using ActiveState Python 2.3.2 on Windows XP Pro. Thanks!

P.S. It does work if I say
exec codeobj in d
but I don't understand why.
 
Reply With Quote
 
 
 
 
fishboy
Guest
Posts: n/a
 
      06-06-2004
On 5 Jun 2004 18:46:11 -0700, http://www.velocityreviews.com/forums/(E-Mail Removed) (Nick Jacobson)
wrote:

>This works fine:
>
>x = 1
>def execfunc():
> print x
>execfunc()
>
>So why doesn't this?
>
>s = \
>"""
>x = 1
>def execfunc():
> print x
>execfunc()
>"""
>
>codeobj = compile(s, "<string>", "exec")
>d = {}
>e = {}
>exec codeobj in d, e
>
>Error message:
>Traceback (most recent call last):
> File "C:\Nick\proj\python1.py", line 17, in ?
> exec codeobj in d, e
> File "<string>", line 6, in ?
> File "<string>", line 5, in execfunc
>NameError: global name 'x' is not defined
>
>I'm using ActiveState Python 2.3.2 on Windows XP Pro. Thanks!
>
>P.S. It does work if I say
>exec codeobj in d
>but I don't understand why.


It works because the local and global namespaces are both 'd'. it
doesn't work in the first because it puts 'x' in the local and then
looks in global.

Now, why it puts 'x' in local, I don't know. If this was a quiz, I'd
put "Nested Scope" and pray.

><{{{*>

 
Reply With Quote
 
 
 
 
Nick Jacobson
Guest
Posts: n/a
 
      06-06-2004
fishboy <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>. ..
> On 5 Jun 2004 18:46:11 -0700, (E-Mail Removed) (Nick Jacobson)
> wrote:
>
> >This works fine:
> >
> >x = 1
> >def execfunc():
> > print x
> >execfunc()
> >
> >So why doesn't this?
> >
> >s = \
> >"""
> >x = 1
> >def execfunc():
> > print x
> >execfunc()
> >"""
> >
> >codeobj = compile(s, "<string>", "exec")
> >d = {}
> >e = {}
> >exec codeobj in d, e
> >
> >Error message:
> >Traceback (most recent call last):
> > File "C:\Nick\proj\python1.py", line 17, in ?
> > exec codeobj in d, e
> > File "<string>", line 6, in ?
> > File "<string>", line 5, in execfunc
> >NameError: global name 'x' is not defined
> >
> >I'm using ActiveState Python 2.3.2 on Windows XP Pro. Thanks!
> >
> >P.S. It does work if I say
> >exec codeobj in d
> >but I don't understand why.

>
> It works because the local and global namespaces are both 'd'. it
> doesn't work in the first because it puts 'x' in the local and then
> looks in global.
>
> Now, why it puts 'x' in local, I don't know. If this was a quiz, I'd
> put "Nested Scope" and pray.
>
> ><{{{*>


I don't know either, that's why I asked

And I don't see why assigning both the local and global namespaces to
the variable 'd' fixes it. But to answer that, the latter question
has to be addressed first.

--Nick
 
Reply With Quote
 
Hung Jung Lu
Guest
Posts: n/a
 
      06-06-2004
(E-Mail Removed) (Nick Jacobson) wrote:
> > Now, why it puts 'x' in local, I don't know.

>
> I don't know either, that's why I asked


The name binding in assignment seems to proceed only for locals,
unless a variable is declared as global explicitly. That is, by
default, the supplied global dictionary is read-only, unless the
'global' statment is used explicitly for those variables that you want
to override. Think of this behavior as if the code defined in the s
string were executed inside another nameless function.

#--------------- try this first in console
s='''
x = 1
def f():
print 'globals', globals().keys()
print 'locals', locals().keys()
print x
print 'globals', globals().keys()
print 'locals', locals().keys()
f()
'''
d={}
e={}
a = compile(s, '<string>', 'exec')
exec a in d, e
#--------------- output
globals ['__builtins__']
locals ['x', 'f']
globals ['__builtins__']
locals []
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<string>", line 9, in ?
File "<string>", line 6, in f
NameError: global name 'x' is not defined

#--------------- now try this in console
s='''
global x
x = 1
def f():
print 'globals', globals().keys()
print 'locals', locals().keys()
print x
print 'globals', globals().keys()
print 'locals', locals().keys()
f()
'''
d={}
e={}
a = compile(s, '<string>', 'exec')
exec a in d, e
#--------------- output
globals ['__builtins__', 'x']
locals ['f']
globals ['__builtins__', 'x']
locals []

#--------------- also try this from fresh console
s='''
x = 1
def f():
print 'globals', globals().keys()
print 'locals', locals().keys()
print x
print 'globals', globals().keys()
print 'locals', locals().keys()
f()
'''
a = compile(s, '<string>', 'exec')
exec a
#--------------- output
globals ['a', 's', 'x', '__builtins__', '__name__', 'f', '__doc__']
locals ['a', 's', 'x', '__builtins__', '__name__', 'f', '__doc__']
globals ['a', 's', 'x', '__builtins__', '__name__', 'f', '__doc__']
locals []
1

-------------------------------------------
Therefore, when no dictionary is supplied, it works because it uses
the current globals() and locals() of the current scope, which in the
case of console or module level (i.e., zero indentation) are referring
to the same dictionary. The assignment 'x=1' was performed on the
locals() dictionary for writing. But inside the f() function, the
statement 'print x' pulls the value from the globals() dictionary.
This coincidence of two dictionaries only happens when you run the
code from the module level. If you put the above code inside a
function, it won't work.

#--------------- from a fresh console
def test():
s='''
x = 1
def f():
print 'globals', globals().keys()
print 'locals', locals().keys()
print x
print 'globals', globals().keys()
print 'locals', locals().keys()
f()
'''
a = compile(s, '<string>', 'exec')
exec a

test()
#--------------- output
globals ['__builtins__', '__name__', 'test', '__doc__']
locals ['a', 'x', 's', 'f']
globals ['__builtins__', '__name__', 'test', '__doc__']
locals []
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 14, in test
File "<string>", line 9, in ?
File "<string>", line 6, in f
NameError: global name 'x' is not defined

regards,

Hung Jung
 
Reply With Quote
 
Nick Jacobson
Guest
Posts: n/a
 
      06-07-2004
Thank you very much for the detailed response. But there's still a
problem.

> The name binding in assignment seems to proceed only for locals,
> unless a variable is declared as global explicitly. That is, by
> default, the supplied global dictionary is read-only, unless the
> 'global' statment is used explicitly for those variables that you want
> to override.


Agreed. The global dictionary is not modified.

But here's the thing. From the Python Ref. Manual:

"If the [local variable] definition occurs in a function block, the
scope extends to any blocks contained within the defining one..."

So as long as code is not on the module level, scopes are extended.
e.g. this works fine:

def main():
y = 3
def execfunc():
print y
execfunc()
if __name__ == '__main__':
main()

But, the following code fails, saying that y is undefined:

def main():
s = \
"""
y = 3
def execfunc():
print y
execfunc()
"""
d = {}
e = {}
exec s in d, e

if __name__ == '__main__':
main()

Why not? Because it doesn't realize it's in main()! It thinks it's
on the module level! (I guess the indentation is a clue.)

Now, if it WERE simply code on the module level, it would also work:

y = 3
def execfunc():
print y
execfunc()

because as you explained, y goes in globals(). This is probably why
the scopes don't nest at this level: they normally don't need to.

Conclusion:

Is code from the exec statement on the module level or not? It
doesn't get its locals mapped to globals. But it also doesn't get its
local variables nested. So it gets neither benefit. IMO it should
get one or the other. i.e. the second piece of code should work.

--Nick
 
Reply With Quote
 
Hung Jung Lu
Guest
Posts: n/a
 
      06-07-2004
(E-Mail Removed) (Nick Jacobson) wrote:
>
> "If the [local variable] definition occurs in a function block, the
> scope extends to any blocks contained within the defining one..."


Strictly speaking, the above statement still holds true. That is, from
a lawyer's point of view.

> But, the following code fails, saying that y is undefined:
>
> def main():
> s = \
> """
> y = 3
> def execfunc():
> print y
> execfunc()
> """
> d = {}
> e = {}
> exec s in d, e
>
> if __name__ == '__main__':
> main()


Very good example.

> Conclusion:
>
> Is code from the exec statement on the module level or not? It
> doesn't get its locals mapped to globals. But it also doesn't get its
> local variables nested. So it gets neither benefit. IMO it should
> get one or the other. i.e. the second piece of code should work.


The exec statement is usually considered an slightly advanced topic.
And frankly I think people that use it at the module level would be
minority. So, having its behavior parallel to the case of nested-scope
would seem to make more sense, to me. Remember also that the "global"
statement can be used inside the code string, which is reminiscence
that we are inside a local scope, just like the case of function. So,
if you wish, the inconsistency could be considered as a bug in Python,
and it may even be good idea to submit a bug report. After all, nested
scope is considered a relative new feature, given Python's history
(over a decade.)

Or there may be some obscure way of tweaking things so to convince
Python that it is inside a function scope at the moment of "def
execfunc():"... Anyway, we are talking about voodoo magic here...

regards,

Hung Jung
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Net::SSH.exec Using the "exec" method interactively Guillermo Riojas Ruby 0 11-26-2010 05:17 PM
Runtime.exec(String[]) Doesn't Always Work, bBut Runtime.exec(String) Does Hal Vaughan Java 11 05-22-2006 04:49 PM
exec "statement" VS. exec "statement in globals(), locals() Ted Python 1 07-22-2004 08:51 AM
exec "statement" VS. exec "statement" in globals(), locals() tedsuzman Python 2 07-21-2004 08:41 PM
Backup Exec 9.1: The Backup Exec job engine system service is not responding Christian Falch Computer Support 1 06-23-2004 02:22 AM



Advertisments