tyker1
tyker1

Reputation: 123

Use String as Function handle in Python

im currently writing my own event handling system with python. There i allow user to assign callbacks for each event with a function:

myEventHandlingSystem.addCallback(event_name, event_callback)

However, as each client has a set of event and sometimes the supported event list will be very long. In such situation, manually add each event using the method described above is quite complicated and might also have some mistakes like forgot to assign an event or an event is assigned multiple times with different callbacks by mistake.

What i want to achieve is that as each event has a String name, user should define the callback with exact the same name as the event. So at the end, user just need to provide a list of event, and each callbacks will automatically be associated to the event (of course, the a callback named in other way, the nothing should be assigned to that event) like:

SUPPORTED_EVENT1 = 'evt_Event1'
SUPPORTED_EVENT2 = 'evt_Event2'

clientConfig = json.load(configHandle)
# the json config file contains a field of 'SupportedEventList':[SUPPRTED_EVENT1,...]


def evt_Event1(*args):
    ...

myEventHandlingSystem.addCallbackFromEventList(clientConfig['SupportedEventList'])

Note that the supportedEventList is alway in form of a string list, where each element is the string contains the name of Event. Also the callback is handeled in the file where class for myEventHandlingSystem is defined

Upvotes: 0

Views: 922

Answers (1)

finnkauski
finnkauski

Reputation: 309

A solution to this would be to have a dict with associations between the functions and their names. Remember, functions are first-class objects in python and as such you can store them in a dict like you can store references to any other data. Hence you could do something along the lines of:


def evt_Event1(*args):
    ...

ALLOWED_CALLBACKS = {"evt_Event1": evt_Event1}

supportedEventList = ["evt_Event1",...]

for event in supportedEventList:
  myEventHandlingSystem.addCallback(event, ALLOWED_CALLBACKS[event])

EDIT: So to address the question as it stands now. There is a function in python called globals() which would have a list of the functions defined in a given python file i.e. {"evt_Event1":<function at ...>}

You could do:

SUPPORTED_EVENT1 = 'evt_Event1'
SUPPORTED_EVENT2 = 'evt_Event2'

clientConfig = json.load(configHandle)
# the json config file contains a field of 'SupportedEventList':[SUPPRTED_EVENT1,...]


def evt_Event1(*args):
    ...

GLOBALS = globals()
for callback_name in clientConfig['SupportedEventList']:
 eventSystem.addCallback(GLOBALS[callback_name])

If you wanted a register type API. You could: So you could do something along the lines of:

# ./decorator.py

REGISTERED = {}

def register(func):
     REGISTERED[func.__name__] = func
     return func

and in the main code

from .decorator import REGISTERED, register

@register
def callback():
    ...

Alternatively you could straight away register the new callback into your event handling system using this type of decorator:

def register(func):
    myEventHandlingSystem.addCallback(func.__name__, func)
    return func

Also you could check out pluggy and similar plug in frameworks that allow people to add plugin functionality which sort of fits your pattern.

Upvotes: 2

Related Questions