How to import a list of functions from different files and the execute them in Python?
Question:
There is a main function, which calls functions from several files.
There might be a possibility that the files have been deleted, hence I want to wrap the call of functions with try except block, and also record the time it took to execute the function.
I Have implemented this in a sub optimal way, the following code works, is there a better method to do this?
files
#main.py
#import time
def main():
timer_data = []
functions_to_be_called = []
a=time.time()
functions_to_be_called.append(("from side_branch_1 import side_branch_1","side_branch_1()"))
functions_to_be_called.append(("from side_branch_2 import side_branch", "side_branch()"))
call_function_safely(functions_to_be_called, timer_data)
b=time.time()
timer_data.append({'Func Name' : 'Overall','Time' : round(b - a,2)})
print(timer_data)
def call_function_safely(func_strings, timer_data):
for import_string, func_string in func_strings:
sub_a = time.time()
try:
exec(import_string)
exec(func_string)
except BaseException as error:
print(error)
sub_b = time.time()
timer_data.append({'Func Name' : 'side_branch_1','Time' : round(sub_b - sub_a,2)})
# side_branch_2.py
def side_branch():
print('side branch 2 called')
# side_branch_1.py
def side_branch_1():
print('Side Branch 1 Called')
return 'Side Branch 1'
Answers:
There isn’t anything "safe" about this.
Anyway, the better way to import a module by a string reference is importlib.import_module
.
Then getattr
for the name of the function to call, and then call it.
def call_by_name(module_name, func_name, *args, **kwargs):
try:
mod = importlib.import_module(module_name)
except ImportError:
return None
try:
func = getattr(mod, func_name)
except AttributeError:
return None
return func(*args, **kwargs)
There is a main function, which calls functions from several files.
There might be a possibility that the files have been deleted, hence I want to wrap the call of functions with try except block, and also record the time it took to execute the function.
I Have implemented this in a sub optimal way, the following code works, is there a better method to do this?
files
#main.py
#import time
def main():
timer_data = []
functions_to_be_called = []
a=time.time()
functions_to_be_called.append(("from side_branch_1 import side_branch_1","side_branch_1()"))
functions_to_be_called.append(("from side_branch_2 import side_branch", "side_branch()"))
call_function_safely(functions_to_be_called, timer_data)
b=time.time()
timer_data.append({'Func Name' : 'Overall','Time' : round(b - a,2)})
print(timer_data)
def call_function_safely(func_strings, timer_data):
for import_string, func_string in func_strings:
sub_a = time.time()
try:
exec(import_string)
exec(func_string)
except BaseException as error:
print(error)
sub_b = time.time()
timer_data.append({'Func Name' : 'side_branch_1','Time' : round(sub_b - sub_a,2)})
# side_branch_2.py
def side_branch():
print('side branch 2 called')
# side_branch_1.py
def side_branch_1():
print('Side Branch 1 Called')
return 'Side Branch 1'
There isn’t anything "safe" about this.
Anyway, the better way to import a module by a string reference is importlib.import_module
.
Then getattr
for the name of the function to call, and then call it.
def call_by_name(module_name, func_name, *args, **kwargs):
try:
mod = importlib.import_module(module_name)
except ImportError:
return None
try:
func = getattr(mod, func_name)
except AttributeError:
return None
return func(*args, **kwargs)