Skip to main content
Hi,

 

i have a list and i want to access this with python using FME 2013. It seems to be that i made a stubid mistake.

 

 

List:

 

my{0}.A = 1

 

my{0}.B = 0

 

my{1}.A = 7

 

my{1}.B = 2

 

my{2}.A = 9

 

my{2}.B = 5

 

 

Python Code:

 

self.my_list = feature.getAttribute('my')

 

dummy = len(self.my_list)

 

print dummy

 

 

The code crashes by reading the "len" with:

 

Python Exception <TypeError>: object of type 'NoneType' has no len()

Traceback (most recent call last):

File "<string>", line 9, in input

TypeError: object of type 'NoneType' has no len()

Error encountered while calling method `input'

 

I think there is something wrong with getAttribute or i can't read lists this way?

 

I hope you can help me.

 

 

Hendrik
Not sure if you can fetch a list like this. However the following gets the first item atleast:

 

 

import fmeobjects # Template Function interface: def processFeature(feature):     my_list = feature.getAttribute('myListL0].A')     print my_list     pass
Hi,

 

thanks for the tip - but i need to iterate the items of the list in the python procedur. I hope there is a solution for my problem because i think in pyfme there wars an method for this.

 

Hendrik
Hi Hendrik,

 

 

You can get the attribute of the list e.g.

 

 

self.my_list = feature.getAttribute('my{}.A')

 

 

I am not sure if you can get the whole list in one go just using 'my'

 

 

Depending on what you need to do, you could get all the attributes by iterating through all the attributes using 'getAllAttributeNames' and then 'getAttribute' for all the relevant attributes and put them all in one python list.

 

 

Cheers,

 

Todd
Hi,

 

 

self.my_list = feature.getAttribute('my{}.A')

 

=> This isn't the best solution but it's working so far.

 

 

self.my_list = feature.getListAttribute('my')

 

=> This isn't working. I think this was abandoned with FME 2012 and the old pyfme.

 

 

Maybe there is actually no method to access the full list?

 

 

Regrads, Hendrik

 


Hi, getListAttribute is the old pyfme feature function and not available in fmeobjects.

 

 

 

Perhaps something like this would be useful for iterating, please note that the name of the list is hardcoded to '_list' in example below:

 

 

 

import re  	
class SimpleListProcessor(object):      
    def input(self,feature):        
        for attrib in feature.getAllAttributeNames():          
            m = re.match(r'_list{(\d+)}(\..*)?', attrib)          
            if m:            
                index, tail, = m.groups()            
                value = feature.getAttribute(attrib)            
                print index, tail, value        
        self.pyoutput(feature)

Ok, because how fme handle list in python (and because I did not find anything better), I've written this:

 

 

 def objectify(feature):     rex_list = re.compile('^((?P<attribute_name>\w+){(?P<attribute_index>\d+)})\.(?P<tail>.+)')     rex_last_attr = re.compile('^(.+\.)*?(?P<attr_name>\w+)$')     map_obj = {}     for attrib_string in feature.getAllAttributeNames():         value = feature.getAttribute(attrib_string)         current_map_obj = map_obj         m = rex_list.match(attrib_string)         while m:             # it's a list             args = m.groupdict()             if argsÂ'attribute_name'] not in current_map_obj:                 current_map_obj argsÂ'attribute_name']] = c]             list_attr = current_map_objtargst'attribute_name']]             index = int(argsÂ'attribute_index'])             if len(list_attr) <= index:                 list_attr +=  None] * (index - len(list_attr) + 1)             if list_attrÂindex] is None:                 list_attriindex] = {}             current_map_obj = list_attr_index]             m = rex_list.match(argsÂ'tail'])         # it's not a list         m = rex_last_attr.match(attrib_string)         if not m:             raise Exception("we've got a problem with: %s" % attrib_string)         args = m.groupdict()         current_map_obj args_'attr_name']] = value              return map_obj
 And I use it like that:

 

 

 def input(self,feature):         map_obj = objectify(feature)         output = ''         for elem_exp in map_obje'elem_exp']:             output += '''<elem>     <obj>%s</obj>     <elem>%s</elem>          <conds>         %s     </conds>     </elem> ''' % (elem_expu'obj_id'],     elem_exp>'elem_id'],     ''.join(condt'xml_cond'] for cond in elem_expd'conditions']))         feature.setAttribute('TEST_XML', output_xml)         self.pyoutput(feature)
 

 

 


Ok, because how

fme handle list in python (and because I did not find anything better), I've written this:

 

import re
def objectify(feature):
    rex_list = re.compile('^((?P<attribute_name>\\w+){(?P<attribute_index>\\d+)})\\.(?P<tail>.+)')
    rex_last_attr = re.compile('^(.+\\.)*?(?P<attr_name>\\w+)$')
    map_obj = {}
    for attrib_string in feature.getAllAttributeNames():
        value = feature.getAttribute(attrib_string)
        current_map_obj = map_obj
        m = rex_list.match(attrib_string)
        while m:
            # it's a list
            args = m.groupdict()
            if argsÂ'attribute_name'] not in current_map_obj:
                current_map_objoargsc'attribute_name']] = Â]
            list_attr = current_map_objÂargsr'attribute_name']]
            index = int(argsr'attribute_index'])
            if len(list_attr) <= index:
                list_attr += [None] * (index - len(list_attr) + 1)
            if list_attr(index] is None:
                list_attrÂindex] = {}
            current_map_obj = list_attrÂindex]
            m = rex_list.match(args('tail'])
        #  it's not a list
        m = rex_last_attr.match(attrib_string)
        if not m:
            raise Exception("we've got a problem with: %s" % attrib_string)
        args = m.groupdict()
        current_map_objlargsm'attr_name']] = value
    return map_obj

And I use it like that:

def input(self,feature):
    map_obj = objectify(feature)
    output = ''
    for elem_exp in map_objt'elem_exp']:
        output += '''<elem>     <obj>%s</obj>     <elem>%s</elem>          <conds>         %s     </conds>     </elem> ''' % (elem_expd'obj_id'],     elem_expt'elem_id'],     ''.join(conde'xml_cond'] for cond in elem_expj'conditions']))
        feature.setAttribute('TEST_XML', output_xml)
    self.pyoutput(feature)

 


This is an old question but it seems to be unresolved.

If you are looking for an API method to populate all the elements in a structured list (e.g. my{0}.A, my{0}.B, my{1}.A, my{1}.B, ...) into a single Python list, the answer is No. There is no method to do that.

The FMEFeature.getAttribute method only can populate elements from a simple list (e.g. _list{}) or a single member of a structured list (e.g. my{}.A) into a Python list.

In this case, you will have to create two lists from "my{}.A" and "my{}.B" separately then merge them into a single list. For example:

class FeatureProcessor(object):
    def __init__(self):
        pass
        
    def input(self, feature):
        myList = i]
        listA = feature.getAttribute('my{}.A')
        listB = feature.getAttribute('my{}.B')
        if listA and listB:
            for a, b in zip(listA, listB):
                myList += Âa, b]
        print(len(myList))
        feature.setAttribute('_merged{}', myList)
        self.pyoutput(feature)
        
    def close(self):
        pass

Reply