Yet another story about Sagemath environment

For some reasons, I reconfigured my Sagemath environment recently. This post shares my tips based on my experiences these days.

For beginners, I’m sure this is helpful. But most of you crypto players are no strangers to Sagemath - some of you are experts ig. In that case, I hope you’ll still find something interesting here :D

Our main targets:

  1. (Basic) Use Sagemath in VS Code, with Syntax Parsing and other helps.
  2. Integrating external python packages into Sagemath.
  3. Virtual Environment for Sagemath.

Run sage ×; Import sage

Sagemath supports many special syntaxes for simplicity and convenience. Take the following code as an example, you can use it directly in a console or write it to a main.sage and run it with sage main.sage. Typically, it is least efficient to run code in a console.

1
2
3
4
5
# main.sage
R.<x> = ZZ[]
f = x^2 - 16
print(f.roots())
# [(4, 1), (-4, 1)]

But, as we all know, Sagemath is essentially python-style code, and we can use it exactly as python. In this case, you can import sage like a package and run the code with Sagemath’s built-in python interpreter as sage -python main.py.

1
2
3
4
5
6
# main.py
from sage.all import *
R, x = PolynomialRing(ZZ, 'x').objgen()
f = x**2 - 16
print(f.roots())
# [(4, 1), (-4, 1)]

What are the benefits of this?

As mentioned before, Sagemath supports its own syntax system. When implementing python code, the meaning of some code is implicitly changed. For example, sagemath will use its own type by default for numbers. Another common example is the ^ symbol in sagemath, which is equivalent to ** in python. However, ^ is used in python for xor computation, for which you will have to use ^^ in sagemath instead.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a = 233

# python
print(type(a), a.bit_length())
print(a^2)
'''
<class 'int'> 8
235
'''

# sage
print(type(a), a.nbits())
print(a^2)
'''
<class 'sage.rings.integer.Integer'> 8
54289
'''

In this case, running your code (especially external python packages or projects) directly with Sagemath can easily have an obscure effect on type identification, function calls, etc. This is intolerable for me, so I highly recommend the python-style solution.

I don’t know the exact working mechanism in Sagemath, but this works perfectly: for any data type, function, syntax in Sagemath, you can always find the corresponding python code. In fact, you can always find a main.sage.py after you run sage main.sage, which contains the python-version of your Sagemath codes.

The advantage is that if you implenemt your code entirely in python style, you can introduce python-related tools such as syntax highlighting, which we’ll cover later.

For efficiency, I don’t think there is a significant difference between the two ways. But if you wanna run sage-independent python code, using a python interpreter (not the one in Sagemath) directly is a more efficient choice.

External Python Packages

A simple way to use external python packages is to run pip install in your Sagemath console. Then you can import them in your sage-style/python-style code.

Basic is Enough

Here comes my simple, basic configuration used for years.

I just implement my codes in VS Code and run them in the terminal with sage -python main.py. Of course, you can use Code Runner for some convenience (but I didn’t). The only configuration I do is Pylance, in order to get code highlighting and other tools in programming. Here, the core of the problem lies in the interpreter setting.

To achieve this, we can run the following code in Sagemath console.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# tested on my MacOS
┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 10.6, Release Date: 2025-03-31
│ Using Python 3.12.5. Type "help()" for help. │
└────────────────────────────────────────────────────────────────────┘
sage: import sys
sage: sys.path
['/Applications/SageMath-10-6.app/Contents/Frameworks/Sage.framework/Versions/10.6/local/var/lib/sage/venv-python3.12.5/bin',
'/private/var/tmp/sage-10.6-current/local/var/lib/sage/venv-python3.12.5/lib/python312.zip',
'/private/var/tmp/sage-10.6-current/local/var/lib/sage/venv-python3.12.5/lib/python3.12',
'/private/var/tmp/sage-10.6-current/local/var/lib/sage/venv-python3.12.5/lib/python3.12/lib-dynload',
'',
'/private/var/tmp/sage-10.6-current/local/var/lib/sage/venv-python3.12.5/lib/python3.12/site-packages']
sage: cat /Applications/SageMath-10-6.app/Contents/Frameworks/Sage.framework/Versions/10.6/local/var/lib/sage/venv-python3.12.5/bin/sage-python
#!/bin/sh
sage -python "$@"
sage:

You can find a .../bin path. There’ll always be a sage-python bash file in that folder, which simply runs sage -python "$@". If you set this file as the interpreter in your VS Code, you can parse the syntax of sage-related functions.

1.png

This used to be able to parse external packages, but it stopped working in my VS Code for some reason. My solution is to manually import the .../site-packages path in the outputs above.

In short, you can create the following .vscode/settings.json file:

1
2
3
4
5
6
7
{
"python.defaultInterpreterPath": "/Applications/SageMath-10-6.app/Contents/Frameworks/Sage.framework/Versions/10.6/local/var/lib/sage/venv-python3.12.5/bin/sage-python",
"files.exclude": { // this will hide the following setting files
"**/.vscode": true,
"**/.env": true
}
}

And a .env file:

1
PYTHONPATH="/private/var/tmp/sage-10.6-current/local/var/lib/sage/venv-python3.12.5/lib/python3.12/site-packages"

With the corresponding outputs in your own Sagemath, of course.

For those who favor using Jupyter Notebook, this also works. You just need to use Sagemath as a jupyter kernel, and Pylance will effectively parse your codes.

A Fresh Take

Through further explorations, I discovered a more interesting method. You see, we can use .../bin/sage-python mentioned above as a python interpreter, can we set up a virtual environment using venv? The answer is yes, but it’s just a pure python environment (without sage package).

1
2
3
4
5
6
7
8
9
10
rec:/ $ /Applications/SageMath-10-6.app/Contents/Frameworks/Sage.framework/Versions/10.6/local/var/lib/sage/venv-python3.12.5/bin/sage-python -m venv new_sage_venv
rec:/ $ source new_sage_venv/bin/activate
(new_sage_venv) rec:/ $ python
Python 3.12.5 (main, Feb 25 2025, 12:37:41) [Clang 16.0.0 (clang-1600.0.26.6)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from sage.all import *
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'sage'
>>>

But it turns out that we can import sage by inheriting the system packages with --system-site-packages. In this way, all virtual environments created share the same Sagemath base environment, and we can make special configurations in each of them.

1
2
3
4
5
6
7
8
9
rec:/ $ /Applications/SageMath-10-6.app/Contents/Frameworks/Sage.framework/Versions/10.6/local/var/lib/sage/venv-python3.12.5/bin/sage-python -m venv new_sage_venv --system-site-packages
rec:/ $ source new_sage_venv/bin/activate
(new_sage_venv) rec:/ $ python
Python 3.12.5 (main, Feb 25 2025, 12:37:41) [Clang 16.0.0 (clang-1600.0.26.6)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from sage.all import *
>>> GF
<sage.rings.finite_rings.finite_field_constructor.FiniteFieldFactory object at 0x1099ae490>
>>>

It’s the same if you use sage -python to create one.

The advantages are obvious: pure, independent virtual python environment with sage packages, which makes configuration and package management much easier. We don’t need any additional configurations described earlier. We just need to set the current virtual environment in VS Code and run our code as python main.py, install new package as pip install package

Also, we can use this python interpreter for Jupyter Notebook.

With the new virtual environment, you can create the following .vscode/settings.json file in your VS Code:

1
2
3
4
5
6
7
8
{
"python.defaultInterpreterPath": "new_sage_venv/bin/python",
"python.terminal.activateEnvironment": true, // activate the venv in vscode every time
"files.exclude": { // this will hide the following setting files
"**/.vscode": true,
"**/new_sage_venv": true
}
}

Uhh, the end. I thought there’ll be more to share but it turns out to be simple. Hope you enjoy this!