Python中使用execfile时的NameError

2024-10-01 04:44:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我的应用程序有一个按钮,可以使用execfile动态执行python脚本。如果我在脚本中定义了一个函数(例如spam()),并尝试在另一个函数(例如eggs())中使用该函数,则会出现以下错误:

NameError: global name 'spam' is not defined

egons()内部调用spam()函数的正确方法是什么?

#mainprogram.py
class mainprogram():
    def runme(self):
        execfile("myscript.py")

>>> this = mainprogram()
>>> this.runme()

# myscript.py
def spam():
    print "spam"

def eggs():
    spam()

eggs()

另外,我似乎无法从脚本中的主应用程序执行方法。i、 e

#mainprogram.py
class mainprogram():
    def on_cmdRunScript_mouseClick( self, event ):
        execfile("my2ndscript.py")
    def bleh():
        print "bleh"

 #my2ndscript.py
 bleh()

错误是:

NameError: name 'bleh' is not defined

my2ndscript.py调用bleh()的正确方法是什么?

编辑:更新了第一期


Tags: 方法函数namepy脚本应用程序def错误
3条回答

在第二种情况下,您需要import(不确定“mainprogram.py” 在你的$PYTHONPATH上)

#mainprogram.py
class mainprogram:
    def runme(self):
        execfile("my2ndscript.py")
    def bleh(self):
        print "bleh"
if __name__ == '__main__':
    mainprogram().runme()

#my2ndscript.py
import mainprogram
x = mainprogram.mainprogram()
x.bleh()

但这将创建mainprogram的第二个实例。或者,更好的是:

#mainprogram.py
class mainprogram:
    def runme(self):
        execfile("my2ndscript.py", globals={'this': self})
    def bleh(self):
        print "bleh"
if __name__ == '__main__':
    mainprogram().runme()

#my2ndscript.py
this.bleh()

我想execfile无论如何都不是解决问题的正确方法。 为什么不使用import__import__(以及reload(),以防在两次单击之间脚本发生更改)?

#mainprogram.py
import my2ndscript

class mainprogram:
    def runme(self):
        reload(my2ndscript)
        my2ndscript.main(self)
    def bleh(self):
        print "bleh"

if __name__ == '__main__':
    mainprogram().runme()

#my2ndscript.py
def main(program):
    program.bleh()

你已经3年8个月大了,所以我假设你已经解决了第一个问题,但是考虑到一个解决方案还没有发布(主要是因为没有人对第一个问题有意见),下面是我的解决方案。

[更新]

我提供的最后一个解决方案是不正确的。下面我将提供正确的解决方案,并使用我执行的代码详细解释它。

这个问题是Python内置的execfile()固有的。这也是Python 3.x中函数被弃用的原因之一。

当您在runme()内部执行execfile()时,对象spam()eggs()被加载到方法runme()的命名空间中,而不是全局命名空间中(理想情况下应该是这样)。请考虑以下代码:

myscript.py

def spam():
    print 'spam'

def eggs():
    if 'spam' not in globals():
        print 'method spam() is not present in global namespace'
    spam()

try:
    eggs()
except Exception as e:
    print e

主程序.py

class mainprogram():
    def runme(self):
        execfile("myscript.py")
        print 'Objects lying in local namespace of runme() are -'
        print locals()

this = mainprogram()
this.runme()

解释器输出

>>>import mainprogram
method spam() is not present in global namespace
name 'spam' is not defined
Objects lying in local namespace of runme() are -
{'e': NameError("name 'spam' is not defined",), 'spam': <function spam at 0x000000000000002B>, 'eggs': <function eggs at 0x000000000000002C>, 'self': <mainprogram.mainprogram instance at 0x000000000000002D>}

从输出中可以看到spam()不在全局命名空间中,而在方法runme()的命名空间中。所以假设,正确的调用spam()的方法应该是

def eggs():
    global this
    this.runme.spam()

但是,当它位于runme()的命名空间中时,无法访问spam()。因此,解决方案是在全局命名空间中插入spam(),如下所示:

myscript.py

global spam
def spam():
    print "spam"

def eggs():
    spam()

eggs()

这将确保在globals()字典(即全局命名空间)中创建对对象spam()的引用,使其可从eggs()调用。

Addy689解释了真正的问题:当从函数调用execfile()时,它会出现。execfile()在全局空间中运行良好。这就是为什么答案常常是“对我来说,这很管用”。

但是修改被调用脚本的解决方案可能是不可能的。 所以我在这里报告我认为最好的解决方案,它是在exec()函数的另一个等价问题上找到的(在那篇文章中:https://stackoverflow.com/a/11754346/1808778)。它与execfile()的工作原理相同

def callingFunction(filename)
    # ... 
    d = dict(locals(), **globals())
    execfile(filename, d, d )

该解决方案的优点是,我们不需要知道调用的脚本:执行的是在ifname==main中命名的函数。

相关问题 更多 >