[REQUEST] Persistence of an object instance after Scripting Save

Dear all,
I am currently using the build b2019032509.
I know every time I save a custom scripting library, the library objects and variables are created again from scratch.
Inside my custom scripting libraries, I would like to use the same object instances also after a save command.
For example, in my library I write the following code:

# Singleton class
class Singleton(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

# Catalog class
class Catalog:
	__metaclass__ = Singleton
	def __init__(self):
		self.__globalDict = {}

	def getGlobal(self, key, default):
		return self.__globalDict.setdefault(key, default)

After a save I would like to point to the same “Catalog” instance I had before saving. The “Catalog” object is created on the “valueChanged” event of a tag.

How can I manage this issue?
Thank you a lot.


You can use the dictionary from system.util.getGlobals(). It persists. However, your singleton will never get new code once instantiated this way, and it will leak memory for the scripting infrastructure that old code is referencing. There be dragons.

Thank you.
Could you explain me better?

In order to pick up new/changed jython code in importable script modules, Ignition must start a new interpreter with scopes for each project and for the global scripting project. The first call into a script module after interpreter startup imports it, creating all top-level named objects in the script module (functions, classes, and module-scope variables). All jython objects referenced solely by the old interpreters are garbage collected with the interpreter. Any old jython objects (code or data) referenced by Ignition’s own java objects will persist, with any code objects holding onto and using the old interpreter, though most such cases clean up relatively quickly. The dangerous case is any thread started with system.util.invokeAsynchronous() – those won’t get cleaned up (still running old code) until its function completes or you deliberately kill it.

The system.util.getGlobals() dictionary is a location where you can deliberately persist objects across interpreter restarts. It is generally safe to put native jython or java objects in this dictionary, though some of those can also be changed due to module load/unload or edits in jython’s own standard library. It is unsafe to place your own jython classes or class instances or functions in this dictionary, as they will keep the code they were created with. If you must, you are responsible for replacing such objects with new ones during your script modules’ import phase. If you fail to do so, you will leak the memory held by the old interpreter in its entirety.

Thank you for your clear and deep explanation.