# Loop through perspective dict property in python script

**URL:** <https://forum.inductiveautomation.com/t/loop-through-perspective-dict-property-in-python-script/51651>\
**Category:** Ignition Early Access\
**Created:** [October 6, 2021, 8:41am UTC](https://forum.inductiveautomation.com/t/loop-through-perspective-dict-property-in-python-script/51651 "2021-10-06T08:41:22Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![nader.chinichian](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nader.chinichian/32/9261_2.png) [@nader.chinichian](https://forum.inductiveautomation.com/u/nader.chinichian)\
**Post date:** [October 6, 2021, 8:41am UTC](https://forum.inductiveautomation.com/t/loop-through-perspective-dict-property-in-python-script/51651/1 "2021-10-06T08:41:22Z")

</div>

Hi,  
I have a problem when I want to loop through a dictionary or a list from the Perspective property in python script and it seems the return obj is not python dict/list.

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/9/e/9e2d1741df18772a99149461e0870b9e35df9e63.png)

How can I get perspective property as python dict or List?

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [October 6, 2021, 8:53am UTC](https://forum.inductiveautomation.com/t/loop-through-perspective-dict-property-in-python-script/51651/2 "2021-10-06T08:53:00Z")

</div>

When you use for with a dict like that, you’re iterating through its keys not its values.  
I tend to explicitly ask what I want using:  
`dict1.keys()`  
or  
`dict1.values()`  
or  
`dict1.items()`

Thus your script becomes:

```auto
dict1 = ...
for key, value in dict1.items():
   end = value['end']
   system.perspective.print(end)

```

More info:

> **[How to Iterate Through a Dictionary in Python – Real Python](https://realpython.com/iterate-through-dictionary-python/#iterating-through-keys-directly)**
>
> In this step-by-step tutorial, you'll take a deep dive into how to iterate through a dictionary in Python. Dictionaries are a fundamental data structure, and you'll be able to solve a wide variety of programming problems by iterating through them.

---

<div class="post-metadata">

**Author:** ![nader.chinichian](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nader.chinichian/32/9261_2.png) [@nader.chinichian](https://forum.inductiveautomation.com/u/nader.chinichian)\
**Post date:** [October 6, 2021, 9:27am UTC](https://forum.inductiveautomation.com/t/loop-through-perspective-dict-property-in-python-script/51651/3 "2021-10-06T09:27:12Z")

</div>

By the way why the return dict object from perspective doesn’t have .copy() method?

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [October 6, 2021, 9:31am UTC](https://forum.inductiveautomation.com/t/loop-through-perspective-dict-property-in-python-script/51651/4 "2021-10-06T09:31:05Z")

</div>

Because it’s not a dict, it’s actually a

[com.inductiveautomation.perspective.gateway.script.DotReferenceJythonMap](https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.1/com/inductiveautomation/perspective/gateway/script/DotReferenceJythonMap.html)

object which resembles a dict. However you can convert it to a dict to use copy:

```auto
dictObj = dict1.toDict().copy()

```

If you need to deepcopy though, you’ll need to import copy and use it from there

---

<div class="post-metadata">

**Author:** ![nader.chinichian](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nader.chinichian/32/9261_2.png) [@nader.chinichian](https://forum.inductiveautomation.com/u/nader.chinichian)\
**Post date:** [October 6, 2021, 9:40am UTC](https://forum.inductiveautomation.com/t/loop-through-perspective-dict-property-in-python-script/51651/5 "2021-10-06T09:40:56Z")

</div>

Thank you, Nick.  
I try to import the copy module to use deepcopy() method to make iteration faster. (loop via objects with referencing to perspective property is very slow compare when we copy every thing first and then loop through)  
The code work in the ignition script console but doesn't work in perspctive:

```auto
import copy
s = copy.deepcopy( dict( self.custom.Stack ) )

```

> TypeError: com.inductiveautomation.perspective.gateway.script.PropertyTreeScriptWrapper$ObjectWrapper(): expected 40 args; got 0

What did I miss here?

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [October 6, 2021, 9:50am UTC](https://forum.inductiveautomation.com/t/loop-through-perspective-dict-property-in-python-script/51651/6 "2021-10-06T09:50:49Z")

</div>

Hmm, not sure about that one… that’s one for @paul-griffith. It’s also odd that the object returned when you read an ‘object’ type property of a component is different depending where you read it from:

- from a property binding inside a script transform, it’s as above, a [com.inductiveautomation.perspective.gateway.script.DotReferenceJythonMap](https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.1/com/inductiveautomation/perspective/gateway/script/DotReferenceJythonMap.html)
- from a script event handler (e.g. button onClick), it’s a [com.inductiveautomation.perspective.gateway.script.PropertyTreeScriptWrapper.ObjectWrapper](https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.1/com/inductiveautomation/perspective/gateway/script/PropertyTreeScriptWrapper.ObjectWrapper.html)

If you don’t deepcopy, it works with copy. However just converting the object to a dict should effectively decouple if from the reference to the Perspective property which is really what you’re doing when you use copy/deepcopy on a dict.

The full error I get is:

```auto
Error running action 'dom.onClick' on _Testing/View@D/root/Label_6:
Traceback (most recent call last):
File "<function:runAction>", line 6, in runAction File "C:\Program Files\Inductive Automation\Ignition\user-lib\pylib\copy.py", line 163, in deepcopy y = copier(x, memo) 
File "C:\Program Files\Inductive Automation\Ignition\user-lib\pylib\copy.py", line 257, in _deepcopy_dict y[deepcopy(key, memo)] = deepcopy(value, memo)
File "C:\Program Files\Inductive Automation\Ignition\user-lib\pylib\copy.py", line 190, in deepcopy y = _reconstruct(x, rv, 1, memo) 
File "C:\Program Files\Inductive Automation\Ignition\user-lib\pylib\copy.py", line 329, in _reconstruct y = callable(*args)
File "C:\Program Files\Inductive Automation\Ignition\user-lib\pylib\copy_reg.py", line 93, in __newobj__ return cls. __new__ (cls, *args) TypeError: com.inductiveautomation.perspective.gateway.script.PropertyTreeScriptWrapper$ObjectWrapper(): expected 40 args; got 0

```

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [October 6, 2021, 2:19pm UTC](https://forum.inductiveautomation.com/t/loop-through-perspective-dict-property-in-python-script/51651/7 "2021-10-06T14:19:27Z")

</div>

`deepcopy` is trying to recreate the original object type, which is not what you want. For a ‘normative’ deepcopy operation, you could borrow a trick from JS - encode to JSON and de-encode in a single step, which guarantees you’re dealing with ‘plain’ Python objects.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [October 6, 2021, 9:51pm UTC](https://forum.inductiveautomation.com/t/loop-through-perspective-dict-property-in-python-script/51651/8 "2021-10-06T21:51:31Z")

</div>

> [@paul-griffith](#):
>
> `deepcopy` is trying to recreate the original object type

Ah, so `dict` is only converting the outer object to a dict, it's not converting the nested objects into dicts?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [October 6, 2021, 10:57pm UTC](https://forum.inductiveautomation.com/t/loop-through-perspective-dict-property-in-python-script/51651/9 "2021-10-06T22:57:00Z")

</div>

Right - `dict` is just the Python builtin, and all it does is go a ‘mapping-like object’ and repackage the key : value pairs within into a `dict` at the outermost layer; by design it doesn’t care if one of those values is itself a more complex object.

You could also write your own recursive function that calls `dict` or `list` as appropriate, which _might_ be faster than the json encode/decode round trip, but the added complexity may not be worth it.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [October 7, 2021, 11:10am UTC](https://forum.inductiveautomation.com/t/loop-through-perspective-dict-property-in-python-script/51651/10 "2021-10-07T11:10:38Z")

</div>

> [@paul-griffith](#):
>
> but the added complexity may not be worth it.

I would be shocked if it wasn't worth it. Not to mention the effect on the types of the nested objects.
