D. Brumby
D. Brumby

Reputation: 33

Python: exec "function()"

I'm coding a simple test program in python as part of my greater program, but i would l like to pass a sub function name into the main function, so the main function can run the subfunction.

eg:

import datetime;

def cronjob(repeat, interval, task):
    if (str(repeat) == 'inf'):
        repeat = 99999999999999999999;
    position = 0;
    interval = datetime.timedelta(seconds=interval);
    x = datetime.datetime.now()
    while not (position >= repeat):
        while (datetime.datetime.now() - x < interval):
            pass;
        x = datetime.datetime.now();
        position += 1;
        exec task;

def test():
    print "hello";

cronjob(10, 0.1, 'test');

EDIT: Already fixed this, but since nothing is listed here, let me show you how to do it in case someone else needs it.

I fiddled with eval() and exec, and tried just eval(task). that didn't throw an error, so I tried print eval(task) and sure enough, it listed the function's memory address [that is, test()]. finally, I have used eval(task); to then call that function. below is the code fixing this:

import datetime;

def cronjob(repeat, interval, task):
    if (str(repeat) == 'inf'):
        repeat = 99999999999999999999;
    position = 0;
    interval = datetime.timedelta(seconds=interval);
    x = datetime.datetime.now()
    while not (position >= repeat):
        while (datetime.datetime.now() - x < interval):
            pass;
        x = datetime.datetime.now();
        position += 1;
        eval(task);

def test():
    print "hello";

cronjob(10, 0.1, 'test()');

Upvotes: 0

Views: 2574

Answers (3)

bereal
bereal

Reputation: 34312

In case if you're absolutely sure you want to derive a function from a string, you may want to use a dict as a mapping from strings to functions like follows:

dispatcher = {'dothis': module1.do_this,
              'dothat': module2.to_that}

def foo(fun):
    fun(arg1, arg2)

def bar(action):
    fun = dispatcher.get(action)
    if fun:
       foo(fun)

This will be much more secure (as action is likely to come from the outside) and provide better decoupling of internal code structure from the external API.

Upvotes: 0

Cameron
Cameron

Reputation: 1725

I believe since functions are objects, you can just pass one in to the "controlling" function by name, so you don't need the exec call (which is usually used for dynamic code execution).

e.g.

def foo(a_number, a_function):
    print a_number
    a_number += 1
    a_function(a_number)

def bar(another_number):
    print another_number

foo(5, bar)

should produce the output:
5
6

Upvotes: 0

sleeplessnerd
sleeplessnerd

Reputation: 22801

Why not pass the function object itself to the scheduler ?

test is an object and can be used as an argument too!

def test():
  print "test"

def exe(func):
  func()

exe(test)

Upvotes: 2

Related Questions