ecFlow's documentation is now on readthedocs!

There can be occasions when we want to add variables dynamically i.e. In this example we want to configure the ECF_LOGHOST to the machine where the job is running. ECF_LOGHOST is used by the log server, to view the running output in the GUI.

%include <head.h>

ecflow_client --alter add variable ECG_LOGHOST %HOST% %ECF_NAME%
ecflow_client --alter add variable ECG_LOGPORT 9316 %ECF_NAME%


ecflow_client --alter delete variable ECG_LOGHOST  %ECF_NAME%
ecflow_client --alter delete variable ECG_LOGPORT  %ECF_NAME%

%include <tail.h>

All this works, but it does add a lot of overhead.

In ecflow 5, we can now add/remove variable with the standard child commands init and complete. If the variable of same name already exists, it is updated.

ecflow_client --init=$$ --add "ECF_LOGHOST=${HOST}-log" "ECF_LOGPORT=9316"

The removing is optional.

ecflow_client --complete --remove ECF_LOGHOST ECF_LOGPORT

Python API

The following examples show similar functionality using python api. i.e. set_child_init_add_vars and set_child_complete_del_vars

class Client(object):
    """Encapsulate communication with the ecflow server. This will automatically call
       the child command init()/complete(), for job start/finish. It will also
       handle exceptions and signals, by calling the abort child command.
       *ONLY* one instance of this class, should be used. Otherwise zombies will be created.
    def __init__(self,init_add_vars = False):
        print ("Creating Client") = ecflow.Client()"%ECF_HOST%","%ECF_PORT%")"%ECF_NAME%")"%ECF_PASS%")
        if init_add_vars:
  {"name1":"1", "name2":"2"})
  [ecflow.Variable("name3","3"), ecflow.Variable("name4","4")])
        print("   Only wait 20 seconds, if the server cannot be contacted (note default is 24 hours) before failing")
        # Abort the task for the following signals
        signal.signal(signal.SIGINT,  self.signal_handler)
        signal.signal(signal.SIGHUP,  self.signal_handler)
        signal.signal(signal.SIGQUIT, self.signal_handler)
        signal.signal(signal.SIGILL,  self.signal_handler)
        signal.signal(signal.SIGTRAP, self.signal_handler)
        signal.signal(signal.SIGIOT,  self.signal_handler)
        signal.signal(signal.SIGBUS,  self.signal_handler)
        signal.signal(signal.SIGFPE,  self.signal_handler)
        signal.signal(signal.SIGUSR1, self.signal_handler)
        signal.signal(signal.SIGUSR2, self.signal_handler)
        signal.signal(signal.SIGPIPE, self.signal_handler)
        signal.signal(signal.SIGTERM, self.signal_handler)
        signal.signal(signal.SIGXCPU, self.signal_handler) 
        if platform.system() != "Darwin":
            signal.signal(signal.SIGPWR,  self.signal_handler)
    def at_time(self):
%ecfmicro #
        return datetime.datetime.fromtimestamp(time.time()).strftime('%H:%M:%S')
#ecfmicro %

    def signal_handler(self,signum, frame):
        print('   Aborting: Signal handler called with signal ', signum)"Signal handler called with signal " + str(signum));
    def __enter__(self):
        print('Calling init at: ' + self.at_time())
    def __exit__(self,ex_type,value,tb):
        print ("   Client:__exit__: ex_type:" + str(ex_type) + " value:" + str(value) + "\n   traceback:" + str(tb))
        if ex_type != None:
            print('Calling abort ' + self.at_time())
  "Aborted with exception type " + str(ex_type) + ":" + str(value))
            return False
        print('Calling complete at: ' + self.at_time())
        return False