0

I learnt that exec can create function dynamically from this post Python: dynamically create function at runtime .

I want to create a function on the fly inside an instance method, and use the function after that.

But the code below fails, why?

class A:
    def method_a(self, input_function_str: str):
        exec('''def hello():
            print('123')
        ''')
        
        # hello() # call hello() here leads to NameError


b = A() 
b.method_a()
# hello() # call hello() here also leads to NameError

My goal is that I dynamically create a function based on input_function_str passing from outside, then use that function somewhere in method_a.

Rick
  • 7,007
  • 2
  • 49
  • 79
  • 2
    `exec()` can take things from current scope, but cant add things into the scope, so the `hello` function gets lost afterwards. Anyway, I wouldnt recommend doing it, seems quite unsafe. What is the use case for this? – yedpodtrzitko May 19 '21 at 09:50
  • 3
    Does this answer your question? [Using a function defined in an exec'ed string in Python 3](https://stackoverflow.com/questions/24733831/using-a-function-defined-in-an-execed-string-in-python-3) – Phu Ngo May 19 '21 at 09:50
  • _Please note that without sandboxing and other precautions this opens a massive security hole because the input string can contain malicious code._ See also: https://stackoverflow.com/questions/1832940/why-is-using-eval-a-bad-practice – Jens May 19 '21 at 09:51

1 Answers1

1

Functions defined dynamically inside other functions using exec aren't saved to that functions locals(). If you save it to the globals() scope instead, your code will work, but you would then also be able to call hello() outside of your function scope

def method_a(input_function_str: str = None):
    exec('''def hello():  print('123') ''', globals())
    print('inside scope:')
    hello()

method_a()
print('outside scope:')
hello()

See this answer for more information: Using a function defined in an exec'ed string in Python 3

oskros
  • 3,101
  • 2
  • 9
  • 28