# When are modules and datasets loaded?

**URL:** <https://forum.inductiveautomation.com/t/when-are-modules-and-datasets-loaded/71710>\
**Category:** Ignition\
**Created:** [March 28, 2023, 2:54pm UTC](https://forum.inductiveautomation.com/t/when-are-modules-and-datasets-loaded/71710 "2023-03-28T14:54:54Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Cecil\_Rhoades](https://avatars.discourse-cdn.com/v4/letter/c/e79b87/32.png) [@Cecil\_Rhoades](https://forum.inductiveautomation.com/u/Cecil_Rhoades)\
**Post date:** [March 28, 2023, 2:54pm UTC](https://forum.inductiveautomation.com/t/when-are-modules-and-datasets-loaded/71710/1 "2023-03-28T14:54:54Z")

</div>

I am relatively new to ignition and Python, so pardon my simple question. I have programming experience in other languages though.

I am writing a script, which will run on the server. The scrip will be called from an OPC trigger.

If it use  
from x import Y

When is the import done? My concern is speed of execution, since Python is interpreted. Does it load once, or every time the script is executed?

Also  
I have data, in a database, which I will use as a lookup. I would like to load this into a python dataset once, and access it from memory, rather than accessing the DB each time the code runs. How do I scope this so that it behaves like global variables until I reload it.

Thanks

---

<div class="post-metadata">

**Author:** ![lrose](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/lrose/32/62724_2.png) [@lrose](https://forum.inductiveautomation.com/u/lrose)\
**Post date:** [March 28, 2023, 3:33pm UTC](https://forum.inductiveautomation.com/t/when-are-modules-and-datasets-loaded/71710/2 "2023-03-28T15:33:01Z")

</div>

> [@Cecil\_Rhoades](#):
>
> since Python is interpreted. Does it load once, or every time the script is executed?

> [@Load Jython Classes on Startup](https://forum.inductiveautomation.com/t/load-jython-classes-on-startup/63585/3):
>
> What classes/functions/objects aren’t ? (Project library scripts are pre-loaded into script environments automatically. No need to import. Actually, importing a project script can cause subtle bugs when project hierarchies are saved/reloaded.) Just refer to project library classes/functions/objects by their fully qualified name wherever you need them. Without any import.

> [@Cecil\_Rhoades](#):
>
> How do I scope this so that it behaves like global variables until I reload it.

Start here:

> [@Global Scripting Variables (Library Script Top-Level Vars)](https://forum.inductiveautomation.com/t/global-scripting-variables-library-script-top-level-vars/60516/2):
>
> 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:** ![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:** [March 28, 2023, 3:44pm UTC](https://forum.inductiveautomation.com/t/when-are-modules-and-datasets-loaded/71710/3 "2023-03-28T15:44:02Z")

</div>

> [@Cecil\_Rhoades](#):
>
> When is the import done? My concern is speed of execution, since Python is interpreted. Does it load once, or every time the script is executed?

Your entire script, including imports, is generally "compiled" once (by Ignition itself) into a callable Jython object that we then re-use until the next time you change the script definition. This actually allows Jython to run quite fast; the JVM is very well optimized.

> [@Cecil\_Rhoades](#):
>
> I have data, in a database, which I will use as a lookup. I would like to load this into a python dataset once, and access it from memory, rather than accessing the DB each time the code runs. How do I scope this so that it behaves like global variables until I reload it.

Your options are system.util.getGlobals() _or_ a memory tag, for shared global mutable state. Be careful to only put native Python data structures into globals; adding arbitrary classes you're defining in your own code can lead to memory leaks, because the JVM won't be able to recover all of the Jython scaffolding _around_ your class.

---

<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 28, 2023, 3:54pm UTC](https://forum.inductiveautomation.com/t/when-are-modules-and-datasets-loaded/71710/4 "2023-03-28T15:54:12Z")

</div>

> [@paul-griffith](#):
>
> into a callable Jython object that we then re-use until the next time you change the script definition

Do you actually retain the outer callable? All of the code that needs to persist ends up in the `PyModule`'s global `PyStringMap`.

---

<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:** [March 28, 2023, 4:00pm UTC](https://forum.inductiveautomation.com/t/when-are-modules-and-datasets-loaded/71710/5 "2023-03-28T16:00:36Z")

</div>

Well, it varies across the platform, but the general pattern is to use an appropriate ScriptManager to "compile" into a ScriptManager.ScriptFunction that can be called with whatever args as appropriate.

Different modules do it differently. For instance, in Perspective everything extends from [`ScriptFunctionHelper`](https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.24/com/inductiveautomation/perspective/gateway/script/ScriptFunctionHelper.html) which does the tricky scaffolding of all the required gateway scoped contextual stuff at invocation time.

---

<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 28, 2023, 4:12pm UTC](https://forum.inductiveautomation.com/t/when-are-modules-and-datasets-loaded/71710/6 "2023-03-28T16:12:56Z")

</div>

> [@paul-griffith](#):
>
> but the general pattern is to use an appropriate ScriptManager to "compile" into a ScriptManager.ScriptFunction that can be called with whatever args as appropriate.

Right, that is the new model for extension functions, where Ignition is supplying the `def something()`. But project library scripts can't be treated that way.

Related:

> [@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…
