Hi Mark,
 
 
Try throwing an exception object. For example:
 
-----
 
cursor, connection = None, None
 
try:
 
    # Throw an exception if an unexpected condition has occurred.
 
    if 
<bad condition>:
 
        raise Exception('message')
 
except Exception as ex:
 
    # Catch the exception and re-throw it to abort the translation.
 
    raise ex
 
finally:
 
    # Clean up resources.
 
    # I think it's better to call the "close()" methods here, like this.
 
    if cursor != None:
 
        cursor.close()
 
    if connection != None:
 
        connection.close()
 
    cursor, connection = None, None
 
-----
 
 
Takashi
                
     
                                    
            Thanks Takashi.
 I had tried using raise to throw an exception but thought I'd badly coded when I saw all the red text in the log. Perhaps I expected FME to halt more cleanly than with the exception.
 
 
Updated version:
 
 
import cx_Oracle
 
cursor, connection = None, None
 
 
try:
 
    connection = cx_Oracle.connect('user/pwd@xe')
 
 
    cursor = connection.cursor()
 
    result = cursor.var(cx_Oracle.NUMBER)
 
    cursor.callproc('check_valid_dataset', (123,result))
 
    if result.getvalue() > 0.0:
 
        raise Exception('missing data')
 
 
except cx_Oracle.DatabaseError as e:
 
    error, = e.args
 
    print 'oracle error'
 
    print(error.message)
 
    raise e
 
 
except Exception as e:
 
    print e
 
    raise     
 
     
finally:
 
    if cursor != None:
 
        cursor.close()
 
    if connection != None:
 
        connection.close()
 
      
                
     
                                    
            Unfortunately, I don't think it can be avoided that the red text appears when an exception has been thrown in startup python process.
 
 
If you can read the source dataset by a SQLExecutor or a FeatureReader, the "clean halt" is possible with this implementation.
 
(1) Define a global variable which indicates the condition in the startup script,
 
(2) Create an initiator feature which has an attribute storing the condition, with a PythonCreator,
 
(3) Check the attribute by a Tester, and halt the translation if the value indicates the bad condition.
 
 
Skeleton:
 
-----
 
# Startup Python Script
 
g_condition = 1 # global variable
 
...
 
if 
<bad condition>:
 
    g_condition = 0
 
-----
 
# PythonCreator (expose "condition" attribute)
 
import fmeobjects
 
class FeatureCreator(object):
 
    def close(self):
 
        feature = fmeobjects.FMEFeature()
 
        feature.setAttribute('condition', g_condition) 
        self.pyoutput(feature)
 
-----
 
# Tester
 
Test Clause: condition = 1
 
- Passed => SQLExecutor or FeatureReader (start the translation)
 
- Failed => Terminator or do nothing (halt the translation)
                
     
                                    
            The Tester can also be omitted.
 
-----
 
# PythonCreator
 
import fmeobjects
 
class FeatureCreator(object):
 
    def close(self):
 
        if g_condition == 1:
 
            feature = fmeobjects.FMEFeature()
 
            self.pyoutput(feature)
 
        else:
 
            # log messages if necessary.
 
            pass
                
     
                                    
            As always you supplied a great solution. 
 
Many Thanks!