Python exec() 的行为根据调用位置的不同而有所不同

发布于 2024-09-16 07:34:00 字数 1561 浏览 3 评论 0原文

我有一个 Python 脚本“runme.py”,我试图从下面的“callerX.py”执行它。我正在使用 exec(open(filename).read()) 来完成此任务。正在执行的脚本包含一个简单的类,该类尝试从全局命名空间和时间调用“time()”函数。在函数内部。

在下面的所有示例中,我们使用 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("Tracepoint 2")
mc.main()
print("Tracepoint 3")


caller1.py:(这工作正常,“时间”函数可以在 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("从函数运行:") 跑步()


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

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

print("从主范围运行:") exec(open("runme.py").read())

print("从函数运行:") 跑步()

请注意,在上面的示例中,对“runme.py”全局命名空间中的 time() 函数的调用始终有效,而对 MyClass.main() 中的 time() 函数的调用仅有时有效,具体取决于是否或者文件 runme.py 不是从函数内 exec() 的。

如果我们从函数外部调用 exec() (caller1.py),它就会起作用。如果我们从函数(caller2.py)内部调用 exec(),它将失败并出现异常。如果我们从函数外部调用 exec(),然后从函数内部 (caller3.py) 调用 exec(),则对 exec() 的两次调用都会运行而不会出现异常。

这种行为似乎不一致。有什么想法吗?我知道这是一个人为的示例,但是,它是从一个更复杂的程序中提炼出来的,该程序的要求使我们走到了这一步。

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("Tracepoint 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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

独自唱情﹋歌 2024-09-23 07:34:00

这可能与“from x import *”的工作原理有关。如果您从“顶层”调用它,它将被导入到整个模块的 globals() 中。

但是,如果您在函数内部调用它,它只会导入到函数中的 locals() 中。 exec() 在 caller2 的函数内进行计算;因此 import * 不会进入 globals() 并且“内部”主函数看不到它。

顺便说一句:有趣的是,如果您尝试这样的代码:

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

您将得到一个异常: SyntaxError: import * is not allowed in function 'run'because it is contains a Nested function with free fields

但这正是您正在做的事情执行官,但不知怎的,它却意外地溜了过去。

然而 - 考虑这里的其他答案 - 你为什么不使用其他的东西呢?查看“imp”模块文档 - 特别是函数 find_module 和 load_module。

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.

阳光①夏 2024-09-23 07:34:00

这里有一个想法:不要使用 exec。基本上每次我看到有人使用 execeval 时,都是因为他们不知道已经存在完成相同事情的更好方法;它是阻碍编写动态代码的拐杖,而不是编写更加动态的代码的方法。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文