How to access the exported dictionary in ghPython?

I have a function in one ghpython component that export a dictionary.

    return {'pointP': pt_p, 'loadline': loadline, 'pline': pline,
         'lines': lines, 'p_h': p_h, 'points':pts,
         'section pt': section_pt}

there are several outputs from the component that are the result of the same function.

So sticky dictionary does not work here.

These dictionaries need to be read by the ghPython follows, but since ghPython cannot read dictionary as INPUT, is there other way to work around?

Put it in a list :wink:

return [{'pointP': pt_p, 'loadline': loadline, 'pline': pline,
         'lines': lines, 'p_h': p_h, 'points':pts,
         'section pt': section_pt}]

I first did that but because the whole thing is under developing and will involve may changes, lists will mess it up…

lists inside lists and index numbers will be a lot of noise.

You are not going to see any list…but a simple IronPython dictionary going our of your component output. GH understand data inside lists, the problem that I got providing a simple dictionary, is that you will have as output a list with all the keys you have in the dictionary instead of the typical Ironpython dictionary…but I don’t know if there is another fancy turn around this problem.

I’m working right know in a project using dictionaries all around and I’m binding them to the output variable as a dictionary inside a list; and I don’t need to mess with that list in the destination component, I get just my dictionary Try it and let me know :wink:

Here you have a post in which I’m asking almost for the same question that you are asking about:

Just a dumb question, but since you are feeding the output into another component, why not use just two simple (synchronized) lists instead of one dictionary?

–Mitch

1 Like

Let’s say that this dictionary manages some properties of a custom object that you created. It’s easier just to call that property in the dictionary and change its value, instead of dealing with indexes that represent certain properties in other list. And it make easier to represent that data later (printing it, creating some labels in the model…)

For me is a clearer approach…

Hi guys

I’d like to shed some light on this. So that you know why things are working this way. Please keep in mind: besides reasonable Python programmer goals, while using GhPython we are in Grasshopper land and are using all facilities that come from IronPython.

So, things to keep in mind:

  • A dictionary that is passed as output from a component will be seen as enumerable and will be enumerated. Grasshopper needs enumerated objects, and GhPython buffers results for Grasshopper when it sees them. When you enumerate, it is exactly the same as calling for key in dictionary: in Python. This means that only the keys will be resolved.

  • Because of what is written in the first bullet point, I believe that since ghPython cannot read dictionary as INPUT is actually an issue with the output. The data associated with the key (so-called value) is lost. If an analog to set existed in Grasshopper, but with dictionaries, I could create one when GhPython spots a dictionary, but such a construct is not present in Grasshopper right now.

  • Enumerables of enumerables will not be iterated at the second, deeper lever. This is a general Grasshopper rule that is kept in GhPython simply because of using the Grasshopper SDK. This is because Grasshopper uses data trees.

Here a simple approach for improving this: if all you want is to pass data without it being enumerated (and copied for you), you could hide it in a class. Then GhPython would have no idea about its internals, and would simple leave it up to you to keep things in sync. However, be careful never to modify the contents of the dictionary in downstream components, or things will go wrong, in a difficult-to-debug manner.

Example for a fix:

data-in-dictionary.gh (4.0 KB)

Does it help?

Giulio


Giulio Piacentino
for Robert McNeel & Associates
giulio@mcneel.com

6 Likes

Thanks @piac for the insightful and useful reply :slight_smile: It let me understand better what happens with the dictionaries and outputs.

And just to understand it better: what happens with the way I was using (putting the dictionary in a dummy list)? Is there any bad side effect with that? I found that it works well without enumerating the dictionary (I guess because is actually inside an enumerated object…a list) and passing it through components? indeed, is it not the same than binding it to a class (list are objects at the end)?

Hi, thanks.

This is exactly what I finally use.
And your reply give me more understanding about how the component work.

Great explanation.

Hey @piac. I know this was a while ago but thanks for this. Can you please respond to @Angel question? It also the same question I have. Is there any issue with putting the dictionary in a list?

Thanks

@aononye The best way to pass a dictionary like this is via a class, and this is just my opinion. It’s a little longer, and it shows exactly why it’s there. It allows to pass other data at the same time. After all, you are not OK with enumerating the dictionary because it actually represents 2 different data streams at the same time. So, we might as well find a way that can pass 3 streams at the same time and be happy about it.

About using lists. Yes, lists are an instance. But I see the problem of, possibly, one day the Grasshopper SDK accepting lists-of-lists as trees (in GH2 land), and so using a list with just an item to actually just shield the content from enumeration could be a poor choice in the long term, because eventually the dictionary might be enumerated.

Also, I find it an unfortunate practice when a side-effect is used as a feature, because when I will look back at the code, I will not know why the list was put there in the first place. That being said, there is nothing prohibiting this from being used. Generally, use what makes you feel best with your code.

1 Like

Thanks for your thorough response. Makes a whole lot of sense. I had a follow up question but made it a new topic Automatically recomputing dictionaries in GHPython

1 Like

Just found this now and it has revolutionised my workflow, thank you so much!!! I was previously confined to keeping dictionaries within one component, but knowing I can transfer them seamlessly across components opens up a whole new world!!

Thanks again!

1 Like

Thank you for sharing.