0

I have a program that starts a new thread to run another arbitrary process. My issue is that the name of the function used for the thread is stored inside a variable. My code:

import _thread

def ArbitraryFunction():
    #do function

userIn = "ArbitraryFunction"

try:
    _thread.start_new_thread( userIn, ("Thread-1") )
except:
    print("Failed to start thread.")

I get an error every time I run this code, indicating that I have not specified a function. However the function name is specified, it is simply contained within a variable.

What have I done wrong, and what do I need to do to fix it? Any help would be greatly appreciated!

Aaron Mann
  • 84
  • 9

2 Answers2

1

This is a really bad thing to do, because executing unauthored code is a huge security flaw.

It is possible using eval:

def myFunction():
    return 5

eval('myFunction')()

This allows you to get an object from the namespace (the function) and then execute it. I repeat, this is a very bad practice.

A better way to do it would be to map the functions in a dictionary and then lookup the function based on the name. Because functions are first class objects in Python, you can use them in most data structures eg.

# Create a dict of function names and functions
functions = {'myFunction': myFunction, 'squareroot': sqrt}

# Execute one of the functions
return functions['myFunction']()
Stuart Buckingham
  • 1,574
  • 16
  • 25
  • I understand the security risk. This is a personal project, and I will fix that if I ever feel like open sourcing it. However, the functions selected are implemented as plugins, making it impractical to create a dictionary. – Aaron Mann Jan 14 '20 at 23:18
1
import _thread
import sys


def ArbitraryFunction():
    # do function

userIn = "ArbitraryFunction"

try:
    _thread.start_new_thread(getattr(sys.modules[__name__], userIn), ("Thread-1",))
except Exception as e:
    print("Failed to start thread due to:\n{}".format(e))

Note

second argument to _thread.start_new_thread() needs to be a tuple. To define a tuple with single entry use a tailing comma ("Thread-1",)

Mayank
  • 148
  • 8