Reputation: 1397
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
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()
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))
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
Reputation: 121966
After you've exec
uted 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