Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NameError using execfile in python

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

like image 846
JcMaco Avatar asked Dec 01 '22 12:12

JcMaco


1 Answers

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() inside runme(), the objects spam() and eggs() were loaded into method runme()'s namespace, and not into the global namespace (as they should ideally be). Consider the following code:

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

mainprogram.py

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

this = mainprogram()
this.runme()

Interpreter Output

>>>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>}

From the output you can see that spam() is not in the global namespace, but in method runme()'s namespace. So hypothetically, the correct way to call spam() would have been

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

However, there is no way to access spam() while it is lying inside runme()'s namespace. The solution, therefore, is to insert spam() in the global namespace as follows:

myscript.py

global spam
def spam():
    print "spam"

def eggs():
    spam()

eggs()

This will ensure that a reference to object spam() is created inside the globals() dictionary (i.e., the global namespace), making it callable from eggs().

like image 90
addy689 Avatar answered Dec 03 '22 02:12

addy689