Thursday, January 30, 2020

Python - Powerful eval() - concatenate string as function


eval(expression[globals[locals]])
The arguments are a string and optional globals and locals. If provided, globals must be a dictionary. If provided, locals can be any mapping object.
The expression argument is parsed and evaluated as a Python expression (technically speaking, a condition list) using the globals and locals dictionaries as global and local namespace. If the globals dictionary is present and does not contain a value for the key __builtins__, a reference to the dictionary of the built-in module builtins is inserted under that key before expression is parsed. This means that expression normally has full access to the standard builtins module and restricted environments are propagated. If the locals dictionary is omitted it defaults to the globals dictionary. If both dictionaries are omitted, the expression is executed with the globals and locals in the environment where eval() is called. Note, eval() does not have access to the nested scopes (non-locals) in the enclosing environment.
The return value is the result of the evaluated expression. Syntax errors are reported as exceptions. Example:

def schedule_job(file_name, scheduled_time):
    try:
        err_msg = pre_run_job(get_file(file_name))  
# Return error. if no error, then run the schedule        
        print(err_msg)
        logging.exception(err_msg)  
# Write error to log. If has error, write error to log without affecting other schedules        
        if err_msg == '':
            print('file is OK. Now start the schedule.')
            eval(scheduled_time)(call, ["python", get_file(file_name)])  
# schedule the job            
            run_schedule()
    except Exception as e:
        logging.exception(e)

Here, the argument 'scheduled_time' is actually a function like:
schedule.every(1).second.do()
But since I have lots of schedules to run, I'd rather like to write it into a function so that I don't need to write the whole thing lots of times.
By using eval(), it parses 'scheduled_time' as a function, then I can easily schedule jobs. e.g.

schedule_job('tx/permit/permit.py', 'schedule.every(1).seconds.do')
schedule_job('mt/permit/permit.py', 'schedule.every().monday.at("7:30").do')

No comments:

Post a Comment