My application has a button to execute a python script dynamically using execfile. If I define a function inside the script (eg. spam()) and try to use that function inside another function (eg. eggs()), I get this error:
NameError: global name 'spam' is not defined
What is the correct way to call the spam() function from within eggs()?
#mainprogram.py
class mainprogram():
def runme(self):
execfile("myscript.py")
>>> this = mainprogram()
>>> this.runme()
# myscript.py
def spam():
print "spam"
def eggs():
spam()
eggs()
Also, I can't seem to be able to execute a method from my main application in the script. i.e.
#mainprogram.py
class mainprogram():
def on_cmdRunScript_mouseClick( self, event ):
execfile("my2ndscript.py")
def bleh():
print "bleh"
#my2ndscript.py
bleh()
The error is:
NameError: name 'bleh' is not defined
What is the correct way to call bleh() from my2ndscript.py?
EDIT: Updated first issue
In the second case you will need
import
(not sure whether "mainprogram.py" is on your$PYTHONPATH
)but this will create a second instance of
mainprogram
. Or, better yet:I guess that
execfile
is not the right solution for your problem anyway. Why don't you useimport
or__import__
(andreload()
in case the script changes between those clicks)?Addy689 explained the real problem: it is when calling execfile() from a function that it appears. execfile() works well from the global space. That's why answers are often 'for me it works'.
But the solution to modify the called scripts may not be possible. So I report here the solution I think the best one, found on another equivalent problem with the exec() function (in that post: https://stackoverflow.com/a/11754346/1808778). It works the same with execfile()
Advantage of that solution is that we don't need to know the called script: it is the function nammed in if name == main that is executed.
Are you sure you posted the actual code you are having trouble with? The first script works fine for me.
The second error is to be expected: the name "bleh" is not defined in the outer block, only within the namespace of "mainprogram"
You're 3 years 8 months wiser since you posted so I'm assuming you'd have figured the first issue out, but given that a solution has not yet been posted (primarily because no one seemed to have a problem with the first issue), the following is my solution.
[UPDATED]
The last solution I provided was incorrect. Below I am providing the correct solution and explaining it in detail using code that I executed.
The problem is inherent in Python's
execfile()
builtin. Its one of the reasons that function has been deprecated in Python 3.x.When you executed
execfile()
insiderunme()
, the objectsspam()
andeggs()
were loaded into methodrunme()
's namespace, and not into the global namespace (as they should ideally be). Consider the following code:myscript.py
mainprogram.py
Interpreter Output
From the output you can see that
spam()
is not in the global namespace, but in methodrunme()
's namespace. So hypothetically, the correct way to callspam()
would have beenHowever, there is no way to access
spam()
while it is lying insiderunme()
's namespace. The solution, therefore, is to insertspam()
in the global namespace as follows:myscript.py
This will ensure that a reference to object
spam()
is created inside theglobals()
dictionary (i.e., the global namespace), making it callable fromeggs()
.