# Python script initialization

**URL:** <https://forum.inductiveautomation.com/t/python-script-initialization/20748>\
**Category:** Ignition\
**Tags:** ignition79, scripting\
**Created:** [November 11, 2018, 5:27pm UTC](https://forum.inductiveautomation.com/t/python-script-initialization/20748 "2018-11-11T17:27:25Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![pgmo](https://avatars.discourse-cdn.com/v4/letter/p/d07c76/32.png) [@pgmo](https://forum.inductiveautomation.com/u/pgmo)\
**Post date:** [November 11, 2018, 5:27pm UTC](https://forum.inductiveautomation.com/t/python-script-initialization/20748/1 "2018-11-11T17:27:25Z")

</div>

As I can see, whenever I _save&publish_ my project, Python scripts get reinitialized (both shared and project ones) - if I put a `print "init`" just at the beginning, that line is executed again after _save&publish_.  
My problem is as follows: I use a couple of `global` Python variables to save references to java objects from a JAR library I developed. If I _save&publish_ my project I see that those variable are reinitialized to `None`, but the resources they allocated have not been freed! Moreover if I dump the heap of the client process with `jmap`, I see that the old references are still there. To solve the problem, whenever I _save&publish_ the project, I need to ask my customer to restart the Ignition client - which is not that nice!  
Is there any possibility to listen to _save&publish_ or whatever, so that I can dispose the objects referenced by the global variables and then have a clean restart? Or do you have a cleverer solution where to put the object references I now save in `global` Python variables?

Thanks in advance, regards

Ignition version: 7.9.9 (b2018081621)

---

<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:** [November 12, 2018, 12:13am UTC](https://forum.inductiveautomation.com/t/python-script-initialization/20748/2 "2018-11-12T00:13:11Z")

</div>

Use the dictionary obtained from system.util.getGlobals() to hold such objects. In your script modules, where you would initialize global variables, instead attempt to retrieve from this dictionary. Only if you don’t get the resource you need would you re-initialize it. Or, if the resource includes jython code (that needs to be replaced), close those resources before replacing them with the new versions.

---

<div class="post-metadata">

**Author:** ![pgmo](https://avatars.discourse-cdn.com/v4/letter/p/d07c76/32.png) [@pgmo](https://forum.inductiveautomation.com/u/pgmo)\
**Post date:** [November 12, 2018, 9:35am UTC](https://forum.inductiveautomation.com/t/python-script-initialization/20748/3 "2018-11-12T09:35:56Z")

</div>

Hi pturmel,  
thanks for your suggestion. As of my tests when script restarts, the `global` namespace is empty and I cannot recall the instances I created before _save&publish_. Therefore I’m forced to create new instances of my objects and they collide with the old ones: the old ones are still managing resources, mainly a COM port which is connected to a device I must read from - one of my instance variables is the implementation of a java `interface`, a `listener` which gets called when data comes in from the device: what I see is that after _save&publish_ the old object still manages data coming in.  
It would be nice for me, if I could catch sort of `before_savePublish_event`, so that I can dispose of my old references.

Thanks, regards

---

<div class="post-metadata">

**Author:** ![Sanderd17](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/sanderd17/32/8735_2.png) [@Sanderd17](https://forum.inductiveautomation.com/u/Sanderd17)\
**Post date:** [November 12, 2018, 10:14am UTC](https://forum.inductiveautomation.com/t/python-script-initialization/20748/4 "2018-11-12T10:14:22Z")

</div>

Hi pgmo,

Phil isn’t talking about the global namespace. The global namespace is in the Python scope, and the entire Python scope gets reset when reloading scripts.

Instead, he’s talking about the [`system.utils.getGlobals()`](https://docs.inductiveautomation.com/display/DOC79/system.util.getGlobals) method. This method calls into the Java part of Ignition, and allows you to store more persistent data (only gets cleared on a gateway restart IIRC).

However, the problem here seems that the object keeps listening, so the old script remains active but inaccessible.  
A more robust option would be to reset the connection from time to time. This will give the garbage collector a chance to clean up the old objects, and minimize the need for persistent state.

---

<div class="post-metadata">

**Author:** ![pgmo](https://avatars.discourse-cdn.com/v4/letter/p/d07c76/32.png) [@pgmo](https://forum.inductiveautomation.com/u/pgmo)\
**Post date:** [November 12, 2018, 11:31am UTC](https://forum.inductiveautomation.com/t/python-script-initialization/20748/5 "2018-11-12T11:31:28Z")

</div>

Hi Sanderd17,  
thank you for your reply. One question: you say:

> This method calls into the Java part of Ignition, and allows you to store more persistent data (only gets cleared on a gateway restart IIRC)

I thought that `system.utils.getGlobals()` was a dictionary of all the variables defined in the script scope (i.e. not in a function scope). So: how can I populate the dictionary that is returned by `getGlobals`? Is there anything like `setGlobals`?

> However, the problem here seems that the object keeps listening, so the old script remains active but inaccessible.

Yes, you are right. To give GC a chance to collect unreferenced objects, I programmed a Python function where I remove listeners, close ports and set variables to `None`. If only I could call that function, I would be happy: after calling that function a heap dump with `jmap` shows that memory is clean, as far as my objects are concerned. The problem is: I have no chance to call that function and calling it from time to time is not so good, in my opinion.  
Since the device data are needed only on one page or two, I could allocate/deallocate those objects depending on the page where the operator is. But if by chance the operator is just on those pages that need the device when I issue a _save&publish_, then ... BOOM!!

---

<div class="post-metadata">

**Author:** ![Sanderd17](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/sanderd17/32/8735_2.png) [@Sanderd17](https://forum.inductiveautomation.com/u/Sanderd17)\
**Post date:** [November 12, 2018, 11:56am UTC](https://forum.inductiveautomation.com/t/python-script-initialization/20748/6 "2018-11-12T11:56:21Z")

</div>

I’m sorry, the link didn’t work. Updated it now.

That just gets a dictionary you can write values on.

---

<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:** [November 12, 2018, 12:04pm UTC](https://forum.inductiveautomation.com/t/python-script-initialization/20748/7 "2018-11-12T12:04:02Z")

</div>

To be more specific, the function system.util.getGlobals() is named that way because it _ **is** _ the global scope dictionary for legacy scripts. Each modern script module has its own global scope, more accurately called module scope.

---

<div class="post-metadata">

**Author:** ![pgmo](https://avatars.discourse-cdn.com/v4/letter/p/d07c76/32.png) [@pgmo](https://forum.inductiveautomation.com/u/pgmo)\
**Post date:** [November 12, 2018, 1:56pm UTC](https://forum.inductiveautomation.com/t/python-script-initialization/20748/8 "2018-11-12T13:56:11Z")

</div>

Thanks pturmel and Sanderd17, you are right! I didn’t try to write to that dictionary: by using it, my instance variables now outlive the _save&publish_.
