# Global Scripting Variables (Library Script Top-Level Vars)

**URL:** <https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516>\
**Category:** Ignition\
**Tags:** ignition81, scripting\
**Created:** [June 8, 2022, 8:22pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516 "2022-06-08T20:22:43Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [June 8, 2022, 8:22pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/1 "2022-06-08T20:22:43Z")

</div>

I need a global variable that is shared between a Gateway Startup script, a Gateway Timer script, and a project library script. It seems like the Gateway Startup and Gateway Timer script already share the same scope (they can both find the variable and execute fine), but the project library script throws a `global name 'var' is not defined` error. How do I share the variable with the project library script? (the project the library is in is set as the gateway’s scripting project)

---

<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:** [June 8, 2022, 8:25pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/2 "2022-06-08T20:25:32Z")

</div>

Gateway events sharing the same scope is an artifact of some backwards-compatibility decisions long ago. Generally, you would use a dictionary or similar defined in the top level of your project script. Those you can access by full name from elsewhere. (Elsewhere in the same scope, that is. “project library” isn’t a scope. Project libraries run in the scope they are called from.)

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [June 8, 2022, 8:27pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/3 "2022-06-08T20:27:50Z")

</div>

In that case, the script is being called from a Tag Change event script, which executes on the Gateway, no? So shouldn’t it have access to that global variable?

---

<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:** [June 8, 2022, 8:33pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/4 "2022-06-08T20:33:12Z")

</div>

No, because only gateway events themselves have that funky “scope”–it is a python “scope”, not an Ignition “scope”. Everything else in Ignition follows modern python “scope”, where each script module’s top level is independent of other script module’s top levels.

You really should not use that legacy behavior. There be dragons. Use library script top-level named objects instead.

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [June 8, 2022, 8:34pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/5 "2022-06-08T20:34:53Z")

</div>

> [@pturmel](#):
>
> Use library script top-level named objects instead

Ok, and how would I do that?

---

<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:** [June 8, 2022, 8:40pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/6 "2022-06-08T20:40:56Z")

</div>

In a project script named `myLibraryScript`:

```auto
mySharedVar = 45

def someFunction():
    print mySharedVar
    # the following is discarded as a function-local assignment
    mySharedVar = 200

def anotherFunction():
    global mySharedVar
    mySharedVar = 300

```

In some other script:

```auto
myLibraryScript.mySharedVar = 100
myLibraryScript.someFunction()
myLibraryScript.anotherFunction()
myLibraryScript.someFunction()

```

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [June 8, 2022, 8:45pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/7 "2022-06-08T20:45:06Z")

</div>

Thanks Phil. You’re always so helpful. I didn’t even know this was possible and it’s exactly what I needed.

---

<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:** [June 8, 2022, 8:50pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/8 "2022-06-08T20:50:03Z")

</div>

Be aware that the value will be lost if you edit and save the project--that causes a script restart and the project scripts will be re-run from scratch.

If you need a value that will survive that, you will need to use `system.util.getGlobals()`. Take care with that, though: if you store any custom classes there, you will leak gobs of memory when you edit the origin project. Some more guidance:

> [@\[IGN-5244\]Persist Python Class Object](https://forum.inductiveautomation.com/t/ign-5244-persist-python-class-object/30498):
>
> I am working in Perspective, but this probably applies to other modules as well. I have created user defined classes in the project scripts and I am instantiating them from a view in Perspective. Is there a place I can persist the instance of the object for use between events by the user? Right now I have it serializing to a property on the view, but when I want to work with the object again I have to de-serialize the object in order to work with it again. Having to write custom de-serialize me…

---

<div class="post-metadata">

**Author:** ![amarks](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/amarks/32/45610_2.png) [@amarks](https://forum.inductiveautomation.com/u/amarks)\
**Post date:** [June 8, 2022, 8:54pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/9 "2022-06-08T20:54:09Z")

</div>

Thanks for the heads up. I don’t think I’ll have issues with that with my setup. My library script creates the global var and sets the initial value. This “initialization” script is called from my gateway startup event (which is triggered on a project save) and then the global var is set from within that same startup script and read-only on other scripts.

---

<div class="post-metadata">

**Author:** ![tupanaster](https://avatars.discourse-cdn.com/v4/letter/t/5daacb/32.png) [@tupanaster](https://forum.inductiveautomation.com/u/tupanaster)\
**Post date:** [July 6, 2022, 5:15pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/10 "2022-07-06T17:15:46Z")

</div>

I was looking into saving a dictionary in a tag but I get many errors.

This solution might also be a good approach.

`mySharedVar` will be available forever?

> [@amarks](#):
>
> This “initialization” script is called from my gateway startup event (which is triggered on a project save) and then the global var is set from within that same startup script and read-only on other scripts.

> [@pturmel](#):
>
> Be aware that the value will be lost if you edit and save the project–that causes a script restart and the project scripts will be re-run from scratch.

A script that runs on a gateway update could solve that problem?

---

<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:** [July 6, 2022, 10:21pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/11 "2022-07-06T22:21:38Z")

</div>

> [@tupanaster](#):
>
> `mySharedVar` will be available forever?

Yes and no. As long as there are no errors loading the script it is defined in, it will always _exist_. It may not have the expected value if the script restarts. There are gateway globals from `system.util.getGlobals()` that can help, but there are memory-leakage pitfalls. Search the forum for "getGlobals" for numerous discussions on this.

Consider experimenting yourself until you understand all of the combinations.

---

<div class="post-metadata">

**Author:** ![jlandwerlen](https://avatars.discourse-cdn.com/v4/letter/j/bc8723/32.png) [@jlandwerlen](https://forum.inductiveautomation.com/u/jlandwerlen)\
**Post date:** [March 5, 2023, 7:39pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/12 "2023-03-05T19:39:13Z")

</div>

I'm still struggling to grasp scoping. My desire is to have a script that returns a list or a dictionary, this script would run periodically from a gateway timer. It doesn't matter to me if the variable survives, as it will update as needed.

Getting the variable is where I'm lost. How can I store in a global variable and then retrieve from a project script?

Crude example:

```auto
globalList = []

def doSomething():
	
	#From gateway event
	globalList = ['one1','two2','three3']
	
def getSomething():
	
	#From another script, project script
	return globalList[1]

```

If I execute both from the script console it works. I played around with declaring `globalList` as global but didn't make a different. Can someone please help me understand scoping related to my example?

---

<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:** [March 5, 2023, 8:44pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/13 "2023-03-05T20:44:57Z")

</div>

In `doSomething`, you are assigning a new object to `globalList`, which causes it to become a local name in that function, not to replace the global. You have two approaches to address this:

- use the `global` statement within `doSomething` to override the local treatment, or

- use list methods to **modify** `globalList` in place.

Modifying in place is most convenient when the top-level variable is a dictionary, not a list.

---

<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:** [March 5, 2023, 8:58pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/14 "2023-03-05T20:58:45Z")

</div>

In addition, a module top-level variable in the gateway is not reachable in other projects, and is not reachable in a designer or vision client script environment.

---

<div class="post-metadata">

**Author:** ![jlandwerlen](https://avatars.discourse-cdn.com/v4/letter/j/bc8723/32.png) [@jlandwerlen](https://forum.inductiveautomation.com/u/jlandwerlen)\
**Post date:** [March 5, 2023, 9:48pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/15 "2023-03-05T21:48:19Z")

</div>

Thanks Phil, running in the designer caught me up.

---

<div class="post-metadata">

**Author:** ![Eugene49](https://avatars.discourse-cdn.com/v4/letter/e/c6cbf5/32.png) [@Eugene49](https://forum.inductiveautomation.com/u/Eugene49)\
**Post date:** [September 27, 2025, 1:11pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/16 "2025-09-27T13:11:24Z")

</div>

On my project script, I query database table, and use it as lookup table.

Is this case a good usecase of using global variable in project script? such that I do not have to query database everytime?

and I could transform the lookup table into a dictionary form like so: `lookup[x][y]`? so it is faster? I believe.

---

<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:** [September 27, 2025, 2:03pm UTC](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/17 "2025-09-27T14:03:01Z")

</div>

> [@Eugene49](#):
>
> On my project script, I query database table, and use it as lookup table.

Yes and no. Caching such is a good use of a script global. Do **not** attempt to run the initialization from the DB during the scripts own initialization--that exacerbates the script initialization bug.
