Question

I came across few related answers but not what I want.

Here is the code I have now:

code_str = """
print "this is my global x = " + x
print "And another line is done"
"""

x = 'mystery'

func_template = lambda p: None

func_template.__code__ = compile(code_str, '<string>', 'exec')
func_template() # this executes fine and also has access to x, which i do need.
# func_template('param') # This raises: TypeError: <module>() takes no arguments (1 given)

Some background; The code_str will be coming from a database, and I need to store lots of functions in a dict so I can call any one by name, like below:

all_funcs = {}

# Assuming db_result returns a list of name, code tuples from the databse

for name, code in db_result:
    all_funcs[name] = my_compile(code)

I want to then just call the needed function with the arguments I want if I know the name:

result = all_funcs[by_name](arg1, arg2)

Edit: database is trusted, so I do not need to santize or worry about malicious code.

Was it helpful?

Solution

If you replace the __code__ object of a lambda, you basically redefine the function. The new argcount is determined by __code__.co_argcount, so it doesnt't matter which or how many arguments the lambda took before.

If you want to pass a parameter to your compiled code, you could try to eval your code object directly, passing your parameter in the locals dictionaray:

code_str = """
print "this is my global x = " + x
print "And another line is done"
print param
"""

compiled = compile(code_str, "<string>", "exec")
func_template = lambda p=None: eval(compiled, globals(), {'param': p})

x = "1"
func_template()
func_template("2")

This way you can obviously only pass keyword arguments, it's not possible to use positional arguments. You could also use

func_template = lambda **kwargs: eval(compiled, globals(), **kwargs)

to pass the keyword arguments given to your function directly.

If you need a return value from your function, then you'd need to compile the code in 'eval' mode instead, which means you have to limit your code to an expressions and can't have statements.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top