# Global objects in Perspective Scope

**URL:** <https://forum.inductiveautomation.com/t/global-objects-in-perspective-scope/53688>\
**Category:** Ignition\
**Tags:** ignition80\
**Created:** [December 2, 2021, 5:19pm UTC](https://forum.inductiveautomation.com/t/global-objects-in-perspective-scope/53688 "2021-12-02T17:19:01Z")\
**Posts on this page:** 10\
**Page:** 2

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [February 4, 2022, 9:32pm UTC](https://forum.inductiveautomation.com/t/global-objects-in-perspective-scope/53688/21 "2022-02-04T21:32:10Z")

</div>

Oh okay, I didnt realize that the section that creates the singleton lock just executes when the project script is referenced, so it would ensure that it exists and I could access it that way.

Would there be any benefit to adding that content into the ` __enter__ ` and ` __exit__ ` methods on the singleton class so that I could just do  
`with MyClass as instance` instead of having to get the lock and then the key? Or would it cause an issue if the gateway restarted and potentially the code inside the ` __enter__ ` and ` __exit__ ` methods had potentially changed?

---

<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:** [February 4, 2022, 10:41pm UTC](https://forum.inductiveautomation.com/t/global-objects-in-perspective-scope/53688/22 "2022-02-04T22:41:24Z")

</div>

No, those are instance methods and you can’t get the instance before you lock.

---

<div class="post-metadata">

**Author:** ![tabre.perez](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/tabre.perez/32/13811_2.png) [@tabre.perez](https://forum.inductiveautomation.com/u/tabre.perez)\
**Post date:** [May 25, 2022, 2:47pm UTC](https://forum.inductiveautomation.com/t/global-objects-in-perspective-scope/53688/23 "2022-05-25T14:47:37Z")

</div>

@pturmel Thank you for your detailed explanation here. Can you confirm I am understanding this correctly:

- The script containing the class definition stores a lock in globals if none exists.
- The script containing the class definition instantiates the class and stores it in globals, “inheriting” values from the old instance if it exists in globals.
- When using this class, for example in an event script, we should import the lock from the script containing the class definition, causing that script to run, replacing the class instance in globals. Then we can pull the class instance from globals and use 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:** [May 25, 2022, 3:03pm UTC](https://forum.inductiveautomation.com/t/global-objects-in-perspective-scope/53688/24 "2022-05-25T15:03:19Z")

</div>

Yes, except you don’t import the lock. You just refer to it with a fully-qualified name–that is enough for Ignition to ensure it is imported. You should never import from any Ignition script library. Only import standard python modules (`sys`, `traceback`, etc.) and external stuff you’ve placed in `pylib`.

---

<div class="post-metadata">

**Author:** ![tabre.perez](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/tabre.perez/32/13811_2.png) [@tabre.perez](https://forum.inductiveautomation.com/u/tabre.perez)\
**Post date:** [May 25, 2022, 3:09pm UTC](https://forum.inductiveautomation.com/t/global-objects-in-perspective-scope/53688/25 "2022-05-25T15:09:57Z")

</div>

Okay that makes sense. Thank you for your help.

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [May 25, 2022, 3:41pm UTC](https://forum.inductiveautomation.com/t/global-objects-in-perspective-scope/53688/26 "2022-05-25T15:41:18Z")

</div>

> [@pturmel](#):
>
> You should never import from any Ignition script library.

Why should you never do this? I had an app that we needed to test the code with pytest, and so we ended up importing any modules we used as aliases instead of `code.py`. What this meant is that anything in a folder could not be fully qualified in the test

I.e: `General.Logging` needed to just be imported as `Logging` due to pytest not understanding the folder structure and the alias not allowing a package name.

Is there a technical reason why not to do this? Or just a “you shouldn’t need to do it in 99% of scenarios so just don’t ever do 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:** [May 25, 2022, 4:11pm UTC](https://forum.inductiveautomation.com/t/global-objects-in-perspective-scope/53688/27 "2022-05-25T16:11:37Z")

</div>

There is a scenario **(race condition)** where an import in one script module could capture old code when multiple scripts were updated.

If you need a module to appear under another name, use assignment, not import, just before you use it. In function scope, don't rely on such from outer scopes. Only a reference to the fully-qualified name will ensure you get the latest code.

{ I wouldn't be surprised if jython 2.7 improved this situation, but I don't think it is gone. }

Edit: New bold above. The race has been caught, and a work-around developed:

> [@Project Library Script Initialization Races](https://forum.inductiveautomation.com/t/project-library-script-initialization-races/98636):
>
> Are you annoyed by pseudo-random breakage in Ignition project library scripting? Odd top-level constants being garbled, or operations in the top level that have side effects running twice? Or more? Not happening much, but always around project edits, and sometimes even on gateway restart? Yeah, me too. frowning_face Poking around under the hood back in the spring, for a module development task, I ran across some problematic IA bytecode and pinged some people. But it went nowhere, as I co…

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [May 25, 2022, 4:29pm UTC](https://forum.inductiveautomation.com/t/global-objects-in-perspective-scope/53688/28 "2022-05-25T16:29:35Z")

</div>

> [@pturmel](#):
>
> If you need a module to appear under another name, use assignment, not import

To clarify, by this do you mean:

```auto
Logging = General.Logging
myLogger = Logging.MyLogger()

```

vs

```auto
import General.Logging as Logging
myLogger = Logging.MyLogger()

```

> [@pturmel](#):
>
> just before you use it.

Also, since python uses reference semantics instead of value semantics, even if I created the assignment at the beginning of the script instead of right before use, would it just be a reference to the currently loaded script at that time? And when the gateway scripts restarted due to any changes it would also force that reference to be replaced next time the scripts reloaded? I am curious why this part is necessary?

---

<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:** [May 25, 2022, 5:32pm UTC](https://forum.inductiveautomation.com/t/global-objects-in-perspective-scope/53688/29 "2022-05-25T17:32:12Z")

</div>

> [@kgamble](#):
>
> by this do you mean

Yes.

But the common case should be `myLogger = General.Logging.MyLogger()`

> [@kgamble](#):
>
> I am curious why this part is necessary?

Demonstrated empirically, some time ago. There's a race condition in there somewhere. Use fully-qualified references at time of use for elements in Ignition script libraries.

---

<div class="post-metadata">

**Author:** ![bkarabinchak.psi](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bkarabinchak.psi/32/83567_2.png) [@bkarabinchak.psi](https://forum.inductiveautomation.com/u/bkarabinchak.psi)\
**Post date:** [May 25, 2022, 7:15pm UTC](https://forum.inductiveautomation.com/t/global-objects-in-perspective-scope/53688/30 "2022-05-25T19:15:28Z")

</div>

> [@pturmel](#):
>
> { I wouldn’t be surprised if jython 2.7 improved this situation, but I don’t think it is gone. }

Just ran into the situation today on 8.1.17. It is definitely not gone.

[Previous page](https://forum.inductiveautomation.com/t/global-objects-in-perspective-scope/53688.md?page=1)
