Solved

Transfer python dictionnary between 2 Transformers


Badge

In a PythonCreator, I create a dictionnary. I'd like to use it in the following Transformer, a PythonCaller as an attribute.

So In the Creator, I finish with "return myDict". In the Caller, I call the attribute myDict.

But when I run the project, in the log, it tells me that :

TypeError: 'NoneType' object is not iterable

Do you have any suggestions?

Thanks

icon

Best answer by david_r 29 June 2016, 13:18

View original

16 replies

Userlevel 5

You can either define your dictionary as a global variable:

global my_dict
my_dict = {1: 'a', 2: 'b', 3: 'c'}

Then in a different Python transformer you can access it like this:

global my_dict
my_value = my_dict[1]

Alternatively you can pass the dictionary as JSON strings from one transformer to another using the feature attributes.

To convert a dictionary "my_dict" to JSON and store it in the attribute "my_json":

feature.setAttribute('my_json', json.dumps(my_dict))

Then later on you can read the attribute "my_json" and convert it back to a dictionary:

my_dict = json.loads(feature.getAttribute('my_json))
Badge

Thanks. But, I have a error in my log saying that the dictionnary isn't a string.

I checked printing the type of it. In the Creator, it is a string. But in the Caller, it became a NonType.

global myDict

 

class FeatureCreator(object):

 

def __init__(self):

 

pass

 

def close(self):

 

feature = fmeobjects.FMEFeature()

 

self.pyoutput(feature)

 

myDict = {'Commune' : 'Tokyo'}

 

feature.setAttribute('my_json', json.dumps(myDict))

 

print json.dumps(myDict)

 

print type(json.dumps(myDict))

Is that because I'm doing it in a method in a class?

Badge

You can either define your dictionary as a global variable:

global my_dict
my_dict = {1: 'a', 2: 'b', 3: 'c'}

Then in a different Python transformer you can access it like this:

global my_dict
my_value = my_dict[1]

Alternatively you can pass the dictionary as JSON strings from one transformer to another using the feature attributes.

To convert a dictionary "my_dict" to JSON and store it in the attribute "my_json":

feature.setAttribute('my_json', json.dumps(my_dict))

Then later on you can read the attribute "my_json" and convert it back to a dictionary:

my_dict = json.loads(feature.getAttribute('my_json))

By the way, I'm new on this forum. Do I have to answer in the comment or in a new answer?

Badge

You can either define your dictionary as a global variable:

global my_dict
my_dict = {1: 'a', 2: 'b', 3: 'c'}

Then in a different Python transformer you can access it like this:

global my_dict
my_value = my_dict[1]

Alternatively you can pass the dictionary as JSON strings from one transformer to another using the feature attributes.

To convert a dictionary "my_dict" to JSON and store it in the attribute "my_json":

feature.setAttribute('my_json', json.dumps(my_dict))

Then later on you can read the attribute "my_json" and convert it back to a dictionary:

my_dict = json.loads(feature.getAttribute('my_json))

I also added my_json in the Attributes to Expose. Is that right?

Userlevel 5

I also added my_json in the Attributes to Expose. Is that right?

That's correct!

Userlevel 5

By the way, I'm new on this forum. Do I have to answer in the comment or in a new answer?

You do as you feel :-)

Userlevel 5

Try this instead:

import json
import fmeobjects

class FeatureCreator(object):

    def __init__(self):
        pass

    def close(self):
        feature = fmeobjects.FMEFeature()
        myDict = {'Commune' : 'Tokyo'}
        feature.setAttribute('my_json', json.dumps(myDict))
        self.pyoutput(feature)

Notice how self.pyoutput(feature) always comes last.

Also notice that you have to import the json module.

If you attach a Logger after this PythonCreator you should get:

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Feature Type: `Logger_LOGGED'
Attribute(string): `fme_feature_type' has value `PythonCreator'
Attribute(string): `my_json' has value `{"Commune": "Tokyo"}'
Geometry Type: Unknown (0)
===========================================================================

Hope this helps.

Userlevel 3
Badge +17

Thanks. But, I have a error in my log saying that the dictionnary isn't a string.

I checked printing the type of it. In the Creator, it is a string. But in the Caller, it became a NonType.

global myDict

 

class FeatureCreator(object):

 

def __init__(self):

 

pass

 

def close(self):

 

feature = fmeobjects.FMEFeature()

 

self.pyoutput(feature)

 

myDict = {'Commune' : 'Tokyo'}

 

feature.setAttribute('my_json', json.dumps(myDict))

 

print json.dumps(myDict)

 

print type(json.dumps(myDict))

Is that because I'm doing it in a method in a class?

Hi @slerendu, found two issues.

  • A global variable should be declared in the method definition that refers to the variable. In this case, you have to declare the 'myDict' global variable in the 'close' method.

  • The feature should be output AFTER assigning a value to the global variable. If the feature was output BEFORE assigning a value to the variable, its instance haven't been created yet when the feature arrived to the next PythonCaller.
Userlevel 3
Badge +17

Thanks. But, I have a error in my log saying that the dictionnary isn't a string.

I checked printing the type of it. In the Creator, it is a string. But in the Caller, it became a NonType.

global myDict

 

class FeatureCreator(object):

 

def __init__(self):

 

pass

 

def close(self):

 

feature = fmeobjects.FMEFeature()

 

self.pyoutput(feature)

 

myDict = {'Commune' : 'Tokyo'}

 

feature.setAttribute('my_json', json.dumps(myDict))

 

print json.dumps(myDict)

 

print type(json.dumps(myDict))

Is that because I'm doing it in a method in a class?

In addition, if you save the dictionary into a feature attribute as a JSON document, it's not necessary to use a global variable. See @david_r's answer.

Badge

Try this instead:

import json
import fmeobjects

class FeatureCreator(object):

    def __init__(self):
        pass

    def close(self):
        feature = fmeobjects.FMEFeature()
        myDict = {'Commune' : 'Tokyo'}
        feature.setAttribute('my_json', json.dumps(myDict))
        self.pyoutput(feature)

Notice how self.pyoutput(feature) always comes last.

Also notice that you have to import the json module.

If you attach a Logger after this PythonCreator you should get:

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Feature Type: `Logger_LOGGED'
Attribute(string): `fme_feature_type' has value `PythonCreator'
Attribute(string): `my_json' has value `{"Commune": "Tokyo"}'
Geometry Type: Unknown (0)
===========================================================================

Hope this helps.

Perfect. Thanks a lot.

Someone at my place told me that I can create my dictionnary in a startup python script. Is that a correct use? I find the json method cleaner.

What do you think?

Userlevel 5

Perfect. Thanks a lot.

Someone at my place told me that I can create my dictionnary in a startup python script. Is that a correct use? I find the json method cleaner.

What do you think?

Apples and oranges.

If the dictionary stays the same during the entire translation, I'd just make it a global variable or something like that. You can create a global variable wherever you want, basically, including in a startup script.

If the dictionary is feature specific, I'd go the JSON route.

Badge

Apples and oranges.

If the dictionary stays the same during the entire translation, I'd just make it a global variable or something like that. You can create a global variable wherever you want, basically, including in a startup script.

If the dictionary is feature specific, I'd go the JSON route.

Thanks, it's clearer now.

Badge

Hi @slerendu, found two issues.

  • A global variable should be declared in the method definition that refers to the variable. In this case, you have to declare the 'myDict' global variable in the 'close' method.

  • The feature should be output AFTER assigning a value to the global variable. If the feature was output BEFORE assigning a value to the variable, its instance haven't been created yet when the feature arrived to the next PythonCaller.

Thanks for your answer. My problem was indeed the feature output.

Badge

In addition, if you save the dictionary into a feature attribute as a JSON document, it's not necessary to use a global variable. See @david_r's answer.

When you say global variable, you mean "global myDict" in the PythonCreator or in the startupPythonScript?

Userlevel 3
Badge +17

When you say global variable, you mean "global myDict" in the PythonCreator or in the startupPythonScript?

I thought that you needed to define the global variable in the PythonCreator since I found the declaration within your script. However global variables can be defined anywhere according to your requirement. All depends on what you want to do with scripting ;)

Badge

I thought that you needed to define the global variable in the PythonCreator since I found the declaration within your script. However global variables can be defined anywhere according to your requirement. All depends on what you want to do with scripting ;)

Ok, thanks :-)

Reply