problem with exec: import doesn't seem to work 
Author Message
 problem with exec: import doesn't seem to work

I am loading a script into memory, making some substitutions, and then
execing it.  When I do, I get the error

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "UseCase.py", line 27, in __init__
    exec( NewProgram )
  File "<string>", line 177, in ?
  File "<string>", line 157, in main
NameError: There is no variable named 'sys'

If I write the string NewProgram out to disk before I exec it, it contains
exactly what I expect, including "import sys" as one of the first
uncommented lines.

If I run the program from the file I saved, it works fine.  If I load it
into a string (manually in the interpreter), and exec it, it works!

However, it seems to not be able to resolve the namespace sys when exec'd
from my class.

I've reduced the problem to its core.  Consider the file simple.py (also
attached):
------------ simple.py
#!/usr/bin/env python

import sys

def goo():
  print sys.argv

print sys.argv
goo()
------------ simple.py

If I read this in from the global space, it works:
---- ex

Quote:
>>> code = open( 'simple.py', 'r' ).read()
>>> exec( code )

['']
['']
---- ex

However, if I do it in a function, it fails.
---- ex

Quote:
>>> def foo():

...   code = open( 'simple.py', 'r' ).read()
...   exec( code )
...
Quote:
>>> foo()

['']
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 3, in foo
  File "<string>", line 9, in ?
  File "<string>", line 6, in goo
NameError: There is no variable named 'sys'
---- ex

I don't see how this can't be a bug.  Any help is appreciated.

I'm running Python 2.0 #8 on Windows 2000 Server SP1.

begin 666 brokenexec.py



`
end

begin 666 simple.py


"*"D`
`
end



Fri, 16 May 2003 03:00:00 GMT  
 problem with exec: import doesn't seem to work


Quote:
> I am loading a script into memory, making some substitutions, and then
> execing it.  When I do, I get the error

> Traceback (most recent call last):
>   File "<stdin>", line 1, in ?
>   File "UseCase.py", line 27, in __init__
>     exec( NewProgram )
>   File "<string>", line 177, in ?
>   File "<string>", line 157, in main
> NameError: There is no variable named 'sys'

In other words: there is no 'sys' in either the local or
global namespace that are being searched at that point.

Quote:
> If I write the string NewProgram out to disk before I exec it, it contains
> exactly what I expect, including "import sys" as one of the first
> uncommented lines.

Yes, sys will be included in the current namespace 'X' where that
string is executed.

Quote:
> If I run the program from the file I saved, it works fine.  If I load it
> into a string (manually in the interpreter), and exec it, it works!

Consider what the "current namespace 'X'" is in either of these cases...

Quote:
> However, it seems to not be able to resolve the namespace sys when exec'd
> from my class.

Or, to be precise: "when exec'd in a local namespace".  I.e.: when
the 'X' is a _local_ namespace...

Quote:
> I've reduced the problem to its core.  Consider the file simple.py (also
> attached):
> ------------ simple.py
> #!/usr/bin/env python

> import sys

> def goo():
>   print sys.argv

> print sys.argv
> goo()
> ------------ simple.py

So far, so, indeed, simple.

Quote:
> If I read this in from the global space, it works:
> ---- ex
> >>> code = open( 'simple.py', 'r' ).read()
> >>> exec( code )
> ['']
> ['']
> ---- ex

Here, the 'X' is the global namespace.  The 'import' sets 'sys'
in the global namespace that 'goo' will use...

Quote:
> However, if I do it in a function, it fails.
> ---- ex
> >>> def foo():
> ...   code = open( 'simple.py', 'r' ).read()
> ...   exec( code )
> ...
> >>> foo()
> ['']

...but, here, the 'import' is in a LOCAL namespace -- that of
'foo'.  And 'goo' does NOT search other local namespaces,
apart from its own.  Thus, it can't find 'sys'!

Quote:
> I don't see how this can't be a bug.  Any help is appreciated.

It is, indeed, a bug -- specifically, a bug in your
code as it stands.

You can reproduce the issue without any 'exec'...:

def foo():
    import sys
    def goo():
        print sys.argv
    print sys.argv
    goo()

this will fail in exactly the same way, while the very
same statement suite in global scope would succeed --
because when this suite is in local scope, the import sys
only sets a sys entry in that LOCAL scope, and nested
function goo does NOT search any local scope except its
own; when the suite is in global scope, the import sys
sets a sys entry in that GLOBAL scope, and goo DOES
search the global scope.

Among the various remedies, the most classic and idiomatic
is to change the def statement for goo to
    def goo(sys=sys):
thus explicitly 'priming' the sys entry in goo's local
namespace so that it refers to the same thing inside
goo as 'sys' referred to at the point of goo's definition.

Given the 'exec' statement, you also have alternatives,
e.g:

def foo():
    code = open('simple.py', 'r').read()
    exec code in locals()

the 'in locals()' clause of the exec statement tells it
to use the same dictionary ('locals()') for both local
and global namespaces, so it fixed things again.  As
it happens,

def foo():
    code = open('simple.py', 'r').read()
    exec code in {}

will work just as well (and not 'dirty' foo's local
namespace...).

Alex



Sat, 17 May 2003 03:00:00 GMT  
 problem with exec: import doesn't seem to work


Quote:


> def foo():
>     code = open('simple.py', 'r').read()
>     exec code in locals()

> the 'in locals()' clause of the exec statement tells it
> to use the same dictionary ('locals()') for both local
> and global namespaces, so it fixed things again.  As
> it happens,

> def foo():
>     code = open('simple.py', 'r').read()
>     exec code in {}

> will work just as well (and not 'dirty' foo's local
> namespace...).

So if I understand correctly, exec code in {} will essentially create a new
empty nampspace for the code to run in.  I believe this is what I want as
the code is some one else's script, and I just want it to run as if it
weren't inside my script.

Thanks much for the clarification.

Jason



Sat, 17 May 2003 03:00:00 GMT  
 
 [ 3 post ] 

 Relevant Pages 

1. expect's full_buffer doesn't seem to work

2. set VIDEO_MODE_RESTRICTION=CGA doesn't seem to work

3. ios.gets doesn't seem to work as advertised

4. setting LD_LIBRARY_PATH doesn't seem to work?

5. proc doesn't seem to work in NASM

6. Micro Focus CALL-CONVENTION 8 doesn't seem to work

7. Adagide install doesn't seem to work?

8. Temporarily changing error_reporting()...doesn't seem to work

9. ldap.modify_s doesn't seem to work

10. update doesn't seem to work with scale

11. The VIServer doesn't work when importing/exporting complicated and many input/output VI.

12. Exec doesn't work with other than small memory model

 

 
Powered by phpBB® Forum Software