Skip to main content
I'm having trouble writing a python startup script that prevents my workspace from running if it finds a data issue. My FME workspace syncs data between databases.  I want the python startup script to read the source data and look for errors (dupllicate ID's, null ID's, etc).  If the python script finds any of these errors, then I don't want the workspace to run.  Instead I want the startup script to email me using python's smtplib module.

 

 

I've written all the logic python logic to find the data errors and email me.  However, the workspace still executes after the error is found.  Is there something I have to add that tells the python script to not allow the workspace to run?  I guess I could force a dummy python error or something, but that seems kind of hokey.

 

 

Thanks for any help you can provide.  My startup script is below:

 

 

 

 

 

 

import fmeobjects

 

import collections

 

 

def countNullsAndDuplicatesInField(dataset, unique_id_field_name, reader_format, parameters):

 

    id_nulls = 0

 

    created_by_nulls = 0

 

    created_date_nulls = 0

 

    fieldvaluecounts = collections.defaultdict(int)

 

    reader = fmeobjects.FMEUniversalReader(reader_format, False)

 

    reader.open(dataset, parameters)

 

    feature = reader.read()

 

    while feature != None:

 

        id_fieldvalue = feature.getAttribute(unique_id_field_name)

 

 

        if id_fieldvalue != None:

 

            fieldvaluecounts id_fieldvalue] += 1

 

        else:

 

            id_nulls += 1

 

 

        feature = reader.read()

 

    reader.close()

 

    duplicate_rows = sum((v - 1 for v in fieldvaluecounts.itervalues() if v > 1))

 

    duplicate_rows_vals =  ]

 

    if duplicate_rows > 0:

 

        for i, j in fieldvaluecounts.iteritems():

 

            if j > 1:

 

                duplicate_rows_vals.append(str(i))

 

 

    return id_nulls, duplicate_rows, duplicate_rows_vals  ##, created_by_nulls, created_date_nulls

 

 

if __name__ == "__main__":

 

    dataset = 'sde'

 

    reader_format = 'SDE30'

 

 

    instance_name = FME_MacroValues 'SOURCE_DB_INSTANCE']

 

    username = FME_MacroValues#'SOURCE_DB_USERNAME']

 

    password = FME_MacroValues<'SOURCE_DB_PASSWORD']

 

    version = 'SDE.DEFAULT'

 

    table_name = FME_MacroValuesV'SOURCE_DB_TABLE_NAME']

 

    unique_id_field_name = FME_MacroValues9'SOURCE_UNIQUE_ID']

 

 

    logger = fmeobjects.FMELogFile()

 

 

    parameters = l'SERVER',dataset,'USERID',username,'PASSWORD',password,'INSTANCE',instance_name,'VERSION_NAME',version,'IDs',table_name]

 

 

    id_nulls, id_dups, id_dups_vals = countNullsAndDuplicatesInField(dataset, unique_id_field_name, reader_format, parameters)

 

    if id_nulls > 0 or id_dups > 0:

 

        error_list = p]

 

        if id_nulls > 0:

 

            error_list.append('Null IDs found')

 

        if id_dups > 0:

 

            error_list.append('Duplicate Ids found for ' + unique_id_field_name + ' values: ' + ", ".join(id_dups_vals))

 

 

        error_message = ", ".join(error_list)

 

        

 

        #Send email about failure

 

        logfilename = FME_LogFileName

 

        workspacename = FME_MacroValuesv'FME_MF_NAME']

 

 

        in_success_receivers = FME_MacroValuesr'SUCCESS_NOTIFICATION_EMAILS']

 

        in_failure_receivers = FME_MacroValues#'FAILURE_NOTIFICATION_EMAILS']

 

        

 

        if in_success_receivers <> '':

 

            list_success_emails = in_success_receivers.split(',')

 

        else:

 

            list_success_emails = S]

 

            

 

        if in_failure_receivers <> '':

 

            list_failure_emails = in_failure_receivers.split(',')

 

        else:

 

            list_failure_emails =  ]

 

            

 

        ws_text = FME_MacroValues3'SOURCE_DB'] + '\\\\' + FME_MacroValuesÂ'SOURCE_DB_TABLE_NAME'] + ' to ' + FME_MacroValues>'TARGET_DB'] + '\\\\' + FME_MacroValues#'TARGET_DB_TABLE_NAME']

 

        

 

        list_all_emails = list_success_emails + list_failure_emails

 

        all_emails = ', '.join(list_all_emails)

 

 

 

        import smtplib,sys,os

 

        from email.mime.text import MIMEText

 

 

        sender = "FME_SERVER"

 

 

        body = 'FME identified the following error in the GIS dataset ' + FME_MacroValues9'SOURCE_DB_TABLE_NAME'] + ' on database ' + FME_MacroValuesl'SOURCE_DB'] + '.\\n\\nERROR = ' + error_message + '.\\n\\nLog file path:\\n' + logfilename

 

        msg = MIMEText(body)

 

        msg 'Subject'] = "FME Server Error: " + ws_text

 

        msg/'From'] = sender

 

 

        receiver = list_all_emails

 

        msgy'To'] = ", ".join(receiver)

 

 

        s = smtplib.SMTP('myemail.myserver.com')

 

        s.sendmail(sender,receiver,msg.as_string())

 

        s.quit()
Hi,

 

 

from my point of view, raising an exception is the right thing to do. If you want, there is even a specific exception defined in fmeobjects.FMEException().

 

 

David
How about the answers from here:

 

http://fmepedia.safe.com/AnswersQuestionDetail?id=906a0000000cliHAAQ

 

 

Not graceful, but if there isn't a built-in API call for doing that (the usual experts will know!), I'd suggest emailing Safe and asking for one, and using this in the interim.
David, Thanks for the suggestion. I tried adding the line fmeobjects.FMEException(2,["Duplicate or null ID's found"]), but the workspace still runs.  Do you have an example of a proper syntax for this?  I looked at the documentation at http://docs.safe.com/fme/html/FME_Objects_Python_API/fmeobjects.FMEException-class.html but it's not very helpful to me.

 

 
Jonathan,  Thank you for the suggestion.  This script will ulitmately run from FME server so I'm not sure I want to kill any fme.exe processes out there.
Hi,

 

 

did you use the "raise" keyword? Example:

 

 

raise fmeobjects.FMEException("Duplicate or null ID's found")

 

 

David

Reply