Solved

Set an attributevalue based of the occurence of a substring with the PythonCaller

  • 31 January 2020
  • 6 replies
  • 1 view

Hi there

 

I am trying to write a Python script which should change the value of an attribue based on the occurence of different substrings int the attribute. This is what i managed to create so far:

import fme
import fmeobjects

class FeatureProcessor(object):
    def __init__(self):
        self.featureList = []
        
    def input(self,feature):
        self.featureList.append(feature)
        

    def close(self):
        substring1 = 'blabla'
        for feature in self.featureList:
            if  feature.getAttribute('TestAttribute') == substring1:
                feature.setAttribute('TestAttribute', 'value1')
            else:
                feature.setAttribute('TestAttribute', 'value2')
            self.pyoutput(feature)
            

This script can be executed but isn't doing the job right. Whith this script de Attribute value has to be exatly the same like (==) "string1".

I tried to do it like this, but the script isnt working:

    def close(self):
        substring1 = 'blabla1'
        for feature in self.featureList:
            if  substring1 in feature.getAttribute('TestAttribute'):
                feature.setAttribute('TestAttribute', 'value1')
            else:
                feature.setAttribute('TestAttribute', 'value2')
            self.pyoutput(feature)
            

Can someone help me?

 

PS: I know that i could do the same thing with a conditional statement in the AttributeManager.

 

Edit:

The main problem was that my script was looking for strings in attribute with where, in many cases, the value was missing ("None") . With your help I managed to get the simplest solution:

 

def strings(feature):
    Astring1 = 'test1'                                         
    Avalue1   = 'Value1'                                          
    attr = feature.getAttribute('AttributeToProcess')
    if attr == None:                      # First it has to be checked if there is a value 
        feature.setAttribute('AttributeToProcess', 'NoValue')
    elif Astring1 in attr:                                      
        feature.setAttribute('AttributeToProcess', Avalue)     
    else:
        feature.setAttribute('AttributeToProcess', 'Leftover')
    pass


icon

Best answer by takashi 2 February 2020, 01:17

View original

6 replies

Badge +22

Why do you have the overhead of adding every feature to a list,  and then processing the list?  If your features are being processed independently of one another why not just use the processFeature function  or in the class, do the processing on the input method?

 

This ought to work:

 

def processFeature(feature):
    substring1 = 'blabla'
    attr = feature.getAttribute('TestAttribute')
    if substring1 in attr:
        feature.setAttribute('TestAttribute', 'value1')
    else:
        feature.setAttribute('TestAttribute', 'value2')

 

Badge

Hi @heitob903

its because you want to do the processing in "input" not close sections.

I only use "Close" when collecting a list of values from multiple records to write out as subset

import fme
import fmeobjects

class FeatureProcessor(object):
    def __init__(self):
        pass
    def input(self,feature):
        substring1 = 'blabla1'
        if feature.getAttribute('TestAttribute') == substring1:
             feature.setAttribute('TestAttribute', 'value1')
        else:
             feature.setAttribute('TestAttribute', 'value2')  
        self.pyoutput(feature)

   def close(self):
        pass

 

and if you use close you will need to create a new "feature" record for every row using

feature = fmeobjects.FMEFeature()
Badge +3

Or how about using a bit of RegEx in a StringReplacer instead:

Userlevel 2
Badge +17

Not clear what you intend to do.

Your first script assigns "value1" to TestAttribute if the original string stored in TestAttribute is exactly equal to "blabla", otherwise "value2".

The second script assigns "value1" to TestAttribute if the original string stored in TestAttribute contains "blabla1", otherwise "value2".

What operation do you actually intend to perform?

Note: The second script would cause an error when the original value of TestAttribute wasn't a string or TestAttribute was missing. You don't need to consider such an unexpected error if you use a conditional value setting in a transformer, since FME would interpret data type of the operands appropriately.

[Addition]

This script might work for you. Set the function name "processFeature" to the Class or Function to Process Features parameter.

def processFeature(feature):
    substring1 = 'blabla'
    attr = feature.getAttribute('TestAttribute')
    if attr and substring1 in str(attr):
        feature.setAttribute('TestAttribute', 'value1')
    else:
        feature.setAttribute('TestAttribute', 'value2')

However, I would recommend you to use conditional value setting with a transformer (AttributeManager or AttributeCreator) rather than scripting, unless there is a specific reason for that you have to implement the process with PythonCaller.

Why do you have the overhead of adding every feature to a list,  and then processing the list?  If your features are being processed independently of one another why not just use the processFeature function  or in the class, do the processing on the input method?

 

This ought to work:

 

def processFeature(feature):
    substring1 = 'blabla'
    attr = feature.getAttribute('TestAttribute')
    if substring1 in attr:
        feature.setAttribute('TestAttribute', 'value1')
    else:
        feature.setAttribute('TestAttribute', 'value2')

 

I was not aware this option. But clearly it is the more simple way to do it!

Not clear what you intend to do.

Your first script assigns "value1" to TestAttribute if the original string stored in TestAttribute is exactly equal to "blabla", otherwise "value2".

The second script assigns "value1" to TestAttribute if the original string stored in TestAttribute contains "blabla1", otherwise "value2".

What operation do you actually intend to perform?

Note: The second script would cause an error when the original value of TestAttribute wasn't a string or TestAttribute was missing. You don't need to consider such an unexpected error if you use a conditional value setting in a transformer, since FME would interpret data type of the operands appropriately.

[Addition]

This script might work for you. Set the function name "processFeature" to the Class or Function to Process Features parameter.

def processFeature(feature):
    substring1 = 'blabla'
    attr = feature.getAttribute('TestAttribute')
    if attr and substring1 in str(attr):
        feature.setAttribute('TestAttribute', 'value1')
    else:
        feature.setAttribute('TestAttribute', 'value2')

However, I would recommend you to use conditional value setting with a transformer (AttributeManager or AttributeCreator) rather than scripting, unless there is a specific reason for that you have to implement the process with PythonCaller.

Thanks a lot! In many cases the value of TestAttribute is missing. That was why I got the errors. 

Reply