Question

Python setAttribute list of dict attributes

  • 15 February 2018
  • 6 replies
  • 27 views

Badge

Hello All,

There are a lot of questions around this topic (ie., https://knowledge.safe.com/questions/51878/how-to-setattribute-lists-in-pythoncaller.html), but somehow I'm not able to make it work. Here is the background:

I have an xml that I'm reading it and getting some attributes to pass them in FME for further processing. I have created a list of dict in order to group them, below is the code I'm using:

 

domain.append({'chartnumb_value':chartnumb_value,
'nm_numbers': get_chart_nm_numbers(update),
'region': get_region(update)})
print domain
Here is the print of the above::

[{'nm_numbers': u'3040(P)/17', 'region': u'UNITED ARAB EMIRATES', 'chartnumb_value': u'Chart No: 8101'}]

[{'nm_numbers': u'3027(P)/17', 'region': u'BANGLADESH', 'chartnumb_value': u'Chart No: 8166'}]

[{'nm_numbers': u'3038(P)/17', 'region': u'AUSTRALIA', 'chartnumb_value': u'Chart No: AUS778'}]

I want to get the 'chartnumb_value', 'nm_numbers', and 'region' into separate columns. For this I'm using after the .append the following:

num_items = len(domain)
for i in range(num_items):
chartnumb_value = domain[i]["chartnumb_value"]
feature.setAttribute("_list{{{}}}".format(i), chartnumb_value

When I run the above code, I'm always getting one value, no matter if I append {} after the list in the attributes to expose (_list{}.chartnumb_value)

I've been going in a "loop" to find the solution, but is not working for me any solutions out there, probably (which is obvious) I'm missing something.

 

 

Thanks in advance for all your help on this

 

Cesar


6 replies

Userlevel 2
Badge +17

Hi @csuarez,

Please try:

num_items = len(domain)
for i in range(num_items):
    entry = domain[i]
    for key in entry:
        feature.setAttribute("_list{{{}}}".format(i) + '.' + key, entry[key])

This will create the following attributes on the feature:

'_list{0}.chartnumb_value' has value `Chart No: 8101'
'_list{0}.nm_numbers' has value `3040(P)/17'
'_list{0}.region' has value `UNITED ARAB EMIRATES'
`_list{1}.chartnumb_value' has value `Chart No: 8166'
`_list{1}.nm_numbers' has value `3027(P)/17'
`_list{1}.region' has value `BANGLADESH'
`_list{2}.chartnumb_value' has value `Chart No: AUS778'
`_list{2}.nm_numbers' has value `3038(P)/17'
`_list{2}.region' has value `AUSTRALIA'

Badge

Hi @csuarez,

Please try:

num_items = len(domain)
for i in range(num_items):
    entry = domain[i]
    for key in entry:
        feature.setAttribute("_list{{{}}}".format(i) + '.' + key, entry[key])

This will create the following attributes on the feature:

'_list{0}.chartnumb_value' has value `Chart No: 8101'
'_list{0}.nm_numbers' has value `3040(P)/17'
'_list{0}.region' has value `UNITED ARAB EMIRATES'
`_list{1}.chartnumb_value' has value `Chart No: 8166'
`_list{1}.nm_numbers' has value `3027(P)/17'
`_list{1}.region' has value `BANGLADESH'
`_list{2}.chartnumb_value' has value `Chart No: AUS778'
`_list{2}.nm_numbers' has value `3038(P)/17'
`_list{2}.region' has value `AUSTRALIA'

Hi @DaveAtSafe,

 

I think my problem is related to the actual length of the list of dict. when I print "num_items", I'm always getting 1

 

 

1
{'nm_numbers': u'3040(P)/17', 'region': u'UNITED ARAB EMIRATES', 'chartnumb_value': u'Chart No: 8101'}
1
{'nm_numbers': u'3027(P)/17', 'region': u'BANGLADESH', 'chartnumb_value': u'Chart No: 8166'}
1
{'nm_numbers': u'3038(P)/17', 'region': u'AUSTRALIA', 'chartnumb_value': u'Chart No: AUS778'} 

 

the reason (for me) that is failing is that I'm doing the data processing one at a time, then creating my dict by appending them. I've tried also with the enumerate() option suggested on another response from @takashi, but still I'm always getting either 1 or 0 (using enumerate).

 

 

Any tips on this?

 

Thank you very much for your quickly response 

 

C
Userlevel 2
Badge +17
Hi @DaveAtSafe,

 

I think my problem is related to the actual length of the list of dict. when I print "num_items", I'm always getting 1

 

 

1
{'nm_numbers': u'3040(P)/17', 'region': u'UNITED ARAB EMIRATES', 'chartnumb_value': u'Chart No: 8101'}
1
{'nm_numbers': u'3027(P)/17', 'region': u'BANGLADESH', 'chartnumb_value': u'Chart No: 8166'}
1
{'nm_numbers': u'3038(P)/17', 'region': u'AUSTRALIA', 'chartnumb_value': u'Chart No: AUS778'} 

 

the reason (for me) that is failing is that I'm doing the data processing one at a time, then creating my dict by appending them. I've tried also with the enumerate() option suggested on another response from @takashi, but still I'm always getting either 1 or 0 (using enumerate).

 

 

Any tips on this?

 

Thank you very much for your quickly response 

 

C
Hi @csuarez,

 

If you are populating the domain list from the input features, you may need to use a Python Class to process your data instead of a function. The class allows you to read multiple features to build up your dictionary in the input method, then output the feature with the list in the close method.

 

It would help if you could give me a higher level view of what you are trying to accomplish with the Python.

 

Userlevel 2
Badge +17
Hi @DaveAtSafe,

 

I think my problem is related to the actual length of the list of dict. when I print "num_items", I'm always getting 1

 

 

1
{'nm_numbers': u'3040(P)/17', 'region': u'UNITED ARAB EMIRATES', 'chartnumb_value': u'Chart No: 8101'}
1
{'nm_numbers': u'3027(P)/17', 'region': u'BANGLADESH', 'chartnumb_value': u'Chart No: 8166'}
1
{'nm_numbers': u'3038(P)/17', 'region': u'AUSTRALIA', 'chartnumb_value': u'Chart No: AUS778'} 

 

the reason (for me) that is failing is that I'm doing the data processing one at a time, then creating my dict by appending them. I've tried also with the enumerate() option suggested on another response from @takashi, but still I'm always getting either 1 or 0 (using enumerate).

 

 

Any tips on this?

 

Thank you very much for your quickly response 

 

C
Agreed. And I think  it would not be essential to create the 'domain' list containing dictionaries.

 

class FeatureProcessor(object):
    def __init__(self):
        self.features = []
        
    def input(self, feature):
        self.features.append(feature)
        
    def close(self):
        newFeature = self.features[0]
        for i, feature in enumerate(self.features):
            #
            # TODO: Get or calculate these values.
            # chartnumb_value = ?
            # update = ?
            # num_numbers = get_chart_nm_numbers(update)
            # region = get_region(update)
            #
            newFeature.setAttribute('_list{%d}.chartnumb_value' % i, chartnumb_value)
            newFeature.setAttribute('_list{%d}.num_numbers' % i, num_numbers)
            newFeature.setAttribute('_list{%d}.region' % i, region)
        self.pyoutput(newFeature)

 

Badge

Hi @DaveAtSafe, @takashi,

 

My apologies for the silence on responding, I'm addressing your comments. Truth is I'm "almost" new in python, but very new in FME Python.

 

My script reads an xml (which is btw painful), then extract a specific tag (index value) and then starts to process it based on the index value. This is where I think the problem is. I'm trying to adjust my code to @takashi's suggestion, obviously challenging for me.

Once again, thank you

C

Badge

My apologies, truly for not posting the answer here before, after sending the python code and source to safe (thanks @DaveAtSafe), the new approach is cleaner and easy to use. I'm attaching the code for future references while dealing with this somehow scenarios.

Thanks

Cesar

readxml-safe.fmw

Reply