How can I save python environment into the Itasca save file?

How can I make save file including python environments (variables, classes, objects and external modules which is loaded already)

If I save using itasca.command("""model save 'filename.sav'""") and restore it, the continuing python scripts will not work because the previous python environments are not saved and restored. So, I have to start the entire script from the beginning.

I have found itasca.add_save_variable but this seems works not for objects but for variables.
and it is a very annoying thing to write every variables as arguments when using the function above.

Regards.

Hi @ppk !

I’m not sure this case can be handled as is, since Python session is mostly an API rather than an internal state of 3DEC models.

Depending on whether you built your Python objects through scripting or command lines, you can either:

  • keep your Python scripts close to your 3DEC commands/Fish/sav files,
  • or export the IPython command lines using the %save magic function in IPython console such as, e.g., %save -r "output_file.py" 1-9999

I am sorry I can only suggest trivial solutions, but @3decsupport might have more satisfying answers?

See you!

Hi again!

Well, after having a closer look, it does seem possible to save any Python object into an Itasca savefile : using 3DEC v7.00.146, I can save and restore variables, classes and their instances, and even modules!

Say you type this in your IPython console (demo class from Python documentation):

>>> import itasca as it
>>> class Dog:
...    def __init__(self, name):
...        self.name = name
...        self.tricks = []    # creates a new empty list for each dog
...    def add_trick(self, trick):
...        self.tricks.append(trick)
...    
>>> rosco = Dog('rosco')
>>> rosco.add_trick('bark')
>>> rosco.add_trick('steal bacon')
>>> rosco.tricks
('bark', 'steal bacon')
>>> import numpy as np
>>> it.add_save_variable('rosco')
>>> it.add_save_variable('Dog')
>>> it.add_save_variable('np')
>>> it.get_save_variables()
(b'rosco', b'Dog', b'np')

Now, in the 3DEC console : model save "demo_py_variables.3dsav".

If I open a new session of 3DEC, and make a model restore "demo_py_variables.3dsav" command, I can then restore my Python variables through the common Python locals(), globals(), or vars() entries :

>>> import itasca as it
>>> it.get_save_variables()
(b'rosco', b'Dog', b'np')
>>> rosco = globals()['rosco']
>>> Dog = globals()['Dog']
>>> isinstance(rosco, Dog)
True
>>> rosco.tricks
('bark', 'steal bacon')
>>> np = globals()['np']
>>> np.arange(5)
array([0, 1, 2, 3, 4])

Still, I would keep the Python devs separately from the pure Itasca saves.
To me, it’s easier to keep an overview on your Python developments if you have separated scripts, rather than through exploration of the variables you would have stored directly within the Itasca saves.
Hey, just my opinion!

Good luck, and let us know if you could make your stuff work!

Thank you Theophile!

Finally, I have found a solution to save variables imported from external modules.

This is the main file named as “A1.py”

get_ipython().magic('reset -sf') #command to initialize iPython environment

import itasca as it
#import numpy as np
import b2 as b_2
it.command("python-reset-state false") #the model new command will not affect python environment

print('==start==', 'name space', __name__)

# MODEL CONFIGURATION
it.command("""model new
""")

print('b_2.g_a is ', b_2.g_a)
b_2.g_a = 2.0
print('b_2.g_a is ', b_2.g_a)

it.add_save_variable('b_2')

it.command(f"""
model save 'a_1.sav'
""")

The external module to define global variable is “b2.py”
g_a = 1.0

Then, the Itasca save file which has been saved already is verified as follows

get_ipython().magic('reset -sf') #command to initialize iPython environment

import itasca as it

it.command("python-reset-state false") #the model new command will not affect python environment

print('==start==', 'name space', __name__)

# MODEL CONFIGURATION
it.command("""model new
""")

it.command(f"""
model restore 'a_1.sav'
""")

print('b_2.g_a is', b_2.g_a)

I have found that Itasca softwares save their save files including external python modules (in forms of “OO.py”) which are imported already and they will be extracted in the working directory when the save files are restored.

However, you should add the imported modules as object by using the command it.add_save_variables() to keep the values stored in variables.

Thank you for your help again.

Regards.

Hi!

Thanks for your feedback!

It’s good to know that:

  • you can save custom modules directly in the save file,
  • you can access Python variables directly in restored save files, no need to go through globals().

However, I would draw attention on the possible confusion when you save an updated module in an Itasca save file: the original Python module (b2.py, in your example) and the one stored in the save file (b2 in a_1.sav, in your case) will be different. If you go through the b2.py file, the values/functions/etc… you read might not be the one you stored in your project.

Well again, thanks for your feedback!

You are right.

Actually, I am trying to manage all the global variables by using external module.
Initial value and type of the glbal variables are only defined at the external module, first.
And then, the value of the variables are controlled and modified in the main code files.
So, I can save only one modules insetad of saving all the globals variables.

Regards…