[英]NameError using execfile in python
我的应用程序有一个按钮,使用execfile动态执行python脚本。 如果我在脚本中定义一个函数(例如spam() )并尝试在另一个函数中使用该函数(例如eggs() ),我会收到此错误:
NameError: global name 'spam' is not defined
从eggs()中调用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()
此外,我似乎无法从脚本中的主应用程序执行方法。 即
#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()的正确方法是什么?
编辑 :更新了第一期
自从你发布以来,你已经3年8个月了,所以我假设你已经想出了第一个问题,但考虑到尚未发布解决方案(主要是因为第一个问题似乎没有人出现问题) ),以下是我的解决方案。
我提供的最后一个解决方案不正确。 下面我提供正确的解决方案,并使用我执行的代码详细解释它。
这个问题是Python内置的execfile()
所固有的。 它是Python 3.x中不推荐使用该函数的原因之一。
当你在runme()
执行execfile()
,对象spam()
和eggs()
被加载到方法runme()
的命名空间中,而不是加载到全局命名空间中(理想情况下应该如此) 。 请考虑以下代码:
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
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()
,如下所示:
global spam
def spam():
print "spam"
def eggs():
spam()
eggs()
这将确保在globals()
字典(即全局命名空间)中创建对object spam()
的引用,使其可以从eggs()
调用。
Addy689解释了真正的问题:它是从它出现的函数调用execfile()时。 execfile()在全局空间中运行良好。 这就是为什么答案往往“对我来说有效”。
但是修改被调用脚本的解决方案可能无法实现。 所以我在这里报告我认为最好的解决方案,在exec()函数的另一个等效问题上找到(在该帖子中: https : //stackoverflow.com/a/11754346/1808778 )。 它与execfile()的工作方式相同
def callingFunction(filename)
# ...
d = dict(locals(), **globals())
execfile(filename, d, d )
该解决方案的优点是我们不需要知道被调用的脚本: 如果执行了name == main ,则该函数被命名为nammed。
在第二种情况下,你需要import
(不确定你的$PYTHONPATH
上是否有“mainprogram.py”)
#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()
您确定发布了遇到问题的实际代码吗? 第一个脚本对我来说很好。
第二个错误是预期的:名称“bleh”没有在外部块中定义,只在“mainprogram”的命名空间内定义
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.