Question

I have a manually maintained list of python functions and modules that will be used by a genetic algorithm and I want to be able to repeatedly call these and monitor the results.

test_exec.py

import os
from random import randint

def main():
    toolList = [{'file':'test1.py', 'function':'sum_even_numbers', 'args':['list'], 'return':['int']},
                {'file':'test1.py', 'function':'get_min_even_num', 'args':['list'], 'return':['int']}   ]
    for tool in toolList:
        for i in range(0,3):
            run(tool, [randint(10,99) for j in range(1,randint(2,5))])

def run(tool, args):
    mod = __import__( os.path.basename(tool['file']).split('.')[0])
    func = getattr(mod, tool['function'])
    tool['return'] = func(args)
    print('main called ' + tool['file'] + '->' + tool['function'] + ' with ', args, ' = ', tool['return'])

main()

test1.py

def sum_even_numbers(numbers):
    return sum([i for i in numbers if i % 2 == 0])

def get_min_even_num(numbers):
    return min([i for i in numbers if i % 2 == 0])

# other code in test1.py which we dont want to execute
print('test1.py has been run' )

results of the code:

test1.py has been run
('main called test1.py->sum_even_numbers with ', [30, 66, 25, 45], ' = ', 96)
('main called test1.py->sum_even_numbers with ', [92], ' = ', 92)
('main called test1.py->sum_even_numbers with ', [59, 73], ' = ', 0)
('main called test1.py->get_min_even_num with ', [59, 12, 61, 24], ' = ', 12)
('main called test1.py->get_min_even_num with ', [22], ' = ', 22)
('main called test1.py->get_min_even_num with ', [97, 94], ' = ', 94)

The code works, by calling a function in a module by string, but during the import this executes the entire file. Is there a better way to do this so that the entire module is not run?

Was it helpful?

Solution

When you import something from a module - even a standalone module-level function - the python interpreter has to parse/compile the whole file before giving you access to that function.

In the case of defs, this is harmless - they are just compiled into functions, no harm done. But sometimes you have "code that you don't want to be run", like your print in your example.

The canonical way of blocking code from being executed when you import a module is:

if __name__ == '__main__':
    # code that only gets executed when I explicitly run this module

More reading.

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