开发者

Behavior of Python exec() differs depending on the where it is called from

开发者 https://www.devze.com 2023-01-13 12:51 出处:网络
I have a Python script \'runme.py\' that I am trying to execute from \'callerX.py\' below. I am using exec(open(filename).read()) to accomplish this task. The script being executed contains a simple c

I have a Python script 'runme.py' that I am trying to execute from 'callerX.py' below. I am using exec(open(filename).read()) to accomplish this task. The script being executed contains a simple class that attempts to call the 'time()' function both from the global namespace & inside a function.

In all of the examples below, we are executing the following file using exec():


# runme.py
# this code is being exec()'d by the stand-alone examples 1-3 below:
from time import *

class MyClass():
    def main(self):
        print("Local tracepoint 1")
        t = time()
        print("Local tracepoint 2")

mc = MyClass()
print("Tracepoint 1")
gt = time()
print("Trac开发者_JS百科epoint 2")
mc.main()
print("Tracepoint 3")

caller1.py: (this works properly, the 'time' function can be used within MyClass.main())


print("Run from main scope:")
exec(open("runme.py").read())

caller2.py: (this does not work, fails with the Exception "NameError: global name 'time' is not defined" inside MyClass.main())


def Run():
    exec(open("runme.py").read())

print("Run from function:") Run()

caller3.py: (this works properly, both exec()s run without Exceptions)


def Run():
    exec(open("runme.py").read())

print("Run from main scope:") exec(open("runme.py").read())

print("Run from function:") Run()

Note that in the examples above, the calls to the time() function in the global namespace of 'runme.py' always work, and the calls to the time() function from MyClass.main() only sometimes work, depending on whether or not the file runme.py was exec()'d from within a function.

If we call exec() from outside a function (caller1.py), it works. If we call exec() from inside a function (caller2.py), it fails with an Exception. If we call exec() from outside a function and subsequently from inside a function (caller3.py), both calls to exec() run without an Exception.

This behavior seems inconsistent. Any ideas? I know this is a contrived example, however, it was distilled from a much more complicated program that has requirements that have brought us to this juncture.


This has probably to do with how 'from x import *' works. If you call this from 'top-level', it gets imported into globals() for the whole module.

However, if you call this inside a function, it gets imported only into locals() - in the function. The exec() gets evaluated inside a function in caller2; therefore the import * doesn't get into globals() and the 'inner' main function doesn't see it.

BTW: it is intersting that if you try code like this:

def run():
    from time import *
    def test():
        print time()
    test()
run()

You will get an exception: SyntaxError: import * is not allowed in function 'run' because it is contains a nested function with free variables

But that is precisely what you are doing with the exec, but it somehow surprisingly sneaks through.

However - considering the other answer here - why don't you use something other instead? Look at the 'imp' module documentation - in particular functions find_module and load_module.


Here's an idea: don't use exec. Basically every time I've seen someone use exec or eval it's because they don't know that a better way to accomplish the same thing already exists; it's a crutch that hinders writing dynamic code, not a way to write code that's somehow more dynamic.

0

精彩评论

暂无评论...
验证码 换一张
取 消