Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i get python function object from a string [duplicate]

I have python functions in string format and I want to get the python objects of these functions in the scope of the program. I have tried exec(), eval() and ast.literal_eval() but none of these return a function object.

For example:

s = "def add(args):\n    try:\n        return sum([int(x) for x in args])\n    except Exception as e:\n        return 'error'\n

this is a simple function in string to add elements of a list. I am looking for a module of utility which can return the object of the function add

function_obj = some_function(s)
print 'type:', type(function_obj)
type: <type 'function'>
like image 984
vasu gaur Avatar asked Mar 04 '23 11:03

vasu gaur


2 Answers

First compile the function(as string) into code object ie,

code_obj = compile(s, '<string>', 'exec')

and then use types.FunctionType to create new function type from code object.

>>> import types
>>> new_func_type = types.FunctionType(code_obj.co_consts[0], globals())
>>> print(type(new_func_type))
<class 'function'>
>>> new_func_type([*range(10)])
45
like image 59
Abdul Niyas P M Avatar answered Mar 16 '23 00:03

Abdul Niyas P M


One way (there might be better ones - e.g. [Python.Docs]: Built-in functions - compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1) as pointed out by @Abdul-Niyas-P-M's answer) would be to:

  • Use [Python 3.Docs]: Built-in Functions - exec(object, globals=None, locals=None, /, *, closure=None), to execute the code, but in a restricted scope

  • Wrap it in a function

>>> s = "def add(args):\n    try:\n        return sum([int(x) for x in args])\n    except Exception as e:\n        return 'error'"
>>>
>>> def create_func_obj(func_code_str):
...     g = dict()
...     l = dict()
...     exec(func_code_str, g, l)
...     if l:
...         return list(l.values())[0]
...
>>>
>>> func = create_func_obj(s)
>>>
>>> func
<function add at 0x000002952F0DEC80>
>>> func([1, 2, 3])
6
>>>
>>> add  # The function wasn't added in the global namespace (as an exec sideeffect)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'add' is not defined

If the code string contains other things besides the definition of one function, the results will not be the expected ones.

like image 27
CristiFati Avatar answered Mar 16 '23 00:03

CristiFati