3.8 Saving and Loading Individual Objects

Suppose you compute a matrix or worse, a complicated space of modular symbols, and would like to save it for later use. What can you do? There are several approaches that computer algebra systems take to saving individual objects.

  1. Save your Game: Only support saving and loading of complete sessions (e.g., GAP, Magma).
  2. Unified Input/Output: Make every object print in a way that can be read back in (GP/PARI).
  3. Eval: Make it easy to evaluate arbitrary code in the interpreter (e.g., Singular, PARI).

Because Sage uses Python it takes a different approach, which is that every object can be serialized, i.e., turned into a string from which that object can be recovered. This is in spirit similar to the unified I/O approach of PARI, except it doesn't have the drawback that objects print to screen in too complicated of a way. Also, support for saving and loading is (in most cases) completely automatic, requiring no extra programming; it's simply a feature of Python that was designed into the language from the ground up.

Almost all Sage objects x can be saved in compressed form to disk using save(x, filename) (or in many cases x.save(filename)). To load the object back in use load(filename).

sage: A = MatrixSpace(QQ,3)(range(9))^2
sage: A
[ 15  18  21]
[ 42  54  66]
[ 69  90 111]
sage: save(A, 'A')
You should now quit Sage and restart. Then you can get A back:
sage: A = load('A')
sage: A
[ 15  18  21]
[ 42  54  66]
[ 69  90 111]
You can do the same with more complicated objects, e.g., elliptic curves. All data about the object that is cached is stored with the object. For example,

sage: E = EllipticCurve('11a')
sage: v = E.anlist(100000)              # takes a while
sage: save(E, 'E')
sage: quit

The saved version of E takes 153 kilobytes, since it stores the first 100000 $ a_n$ with it.

~/tmp$ ls -l E.sobj
-rw-r--r--  1 was was 153500 2006-01-28 19:23 E.sobj
~/tmp$ sage [...]
sage: E = load('E')
sage: v = E.anlist(100000)              # instant!

Note: In Python saving and loading is accomplished using the cPickle module. In particular, a Sage object x can be saved via cPickle.dumps(x, 2). Note the $ 2$ !

Sage cannot save and load individual objects created in some other computer algebra systems, e.g., GAP, Singular, Maxima, etc. They reload in a state marked ``invalid''. In GAP, though many objects print in a form from which they can be reconstructed, many don't, so reconstructing from their print representation is purposely not allowed.

sage: a = gap(2)
sage: a.save('a')
sage: load('a')
Traceback (most recent call last):
...
ValueError: The session in which this object was defined is no longer 
running.

GP/PARI objects can be saved and loaded since their print representation is enough to reconstruct them.

sage: a = gp(2)      
sage: a.save('a')
sage: load('a')
2

Saved objects can be re-loaded later on computers with different architectures or operating systems, e.g., you could save a huge matrix on 32-bit OS X and reload it on 64-bit Linux, find the echelon form, then move it back. Also, in many cases you can even load objects into version of Sage that are different than they were saved in, as long as the code for that object isn't too different. All the attributes of the objects are saved, along with the class (but not source code) that defines the object. If that class no longer exists in a new version of Sage, then the object can't be reloaded in that newer version. But you could load it in an old version, get the objects dictionary (with x.__dict__), and save the dictionary, and load that into the newer version.



Subsections
See About this document... for information on suggesting changes.