Ashisha Nautiyal
Ashisha Nautiyal

Reputation: 1397

Read python function from a text file and assign it to variable

I have a text file that contains Python function like this:

a.txt

def func():
    var = 5
    return var

And then I read this file in a Python script:

b.py

python_file = open("a.txt").read()

Now I want to assign the a.txt file's function to a variable without worrying about the function name and execute it. I tried something like this:

python_file = open("a.txt").read()
b = exec(python_file)
b()

But it didn't work, I tried execfile as well.

Upvotes: 3

Views: 8270

Answers (2)

Hai Vu
Hai Vu

Reputation: 40688

Before offering my solution, I highly warn against do this unless you know for sure there is no malicious code in a.txt.

My solution uses the execfile function to load the text file and return the first object (could be a variable or function):

def load_function(filename):
    """ Assume that filename contains only 1 function """
    global_var = dict()
    execfile(filename, global_var)
    del global_var['__builtins__']
    return next(global_var.itervalues())

# Use it
myfunction = load_function('a.txt')
print myfunction()

Update

To be a little more careful, modify the return line like the following so that it skips variables (it cannot skip class declaration, however).

    return next(f for f in global_var.itervalues() if callable(f))

Update 2

Thank you johnsharpe for pointing out that there is no execfile in Python 3. Here is a modified solution which use exec instead. This time, the function should be found in the "local" scope.

def load_function(filename):
    """ Assume that filename contains only 1 function """
    with open(filename) as f:
        file_contents = f.read()
        global_var = dict()
        local_var = dict()
        exec file_contents in global_var, local_var
        return next(f for f in local_var.itervalues() if callable(f))

# Use it
myfunction = load_function('a.txt')
print myfunction()

Upvotes: 2

jonrsharpe
jonrsharpe

Reputation: 121966

After you've executed the string, you can call func directly, as it has been added to your current namespace:

>>> exec("""def func():
    var = 5  # note that the semicolons are redundant and unpythonic
    return var""")
>>> func()
5

Per its documentation exec doesn't actually return anything, so there's no point assigning e.g. foo = exec(...).


To see what names are locally defined in the code being executed, pass an empty dictionary to exec as the locals parameter:

>>> ns = {}
>>> exec("""def func():
    var = 5
    return var""", globals(), ns)
>>> ns
{'func': <function func at 0x0315F540>}

You can then assign the function and call it as you normally would:

>>> b, = ns.values()  # this will only work if only one name was defined
>>> b()
5

Upvotes: 4

Related Questions