Did something become more strict about circular imports?

49 views
Skip to first unread message

Michael Orlitzky

unread,
Sep 24, 2025, 10:51:32 AM (8 days ago) Sep 24
to sage-...@googlegroups.com
I went to type some sagelib code into ipython this morning, and got a
circular import error. The simplest reproducer is,

$ python -q
>>> from sage.rings.integer_ring import ZZ
...
ImportError: cannot import name 'ZZ' from partially initialized module
'sage.rings.integer_ring' (most likely due to a circular import)
(/home/mjo/.../integer_ring.cpython-313-riscv64-linux-musl.so)

This particular instance is from the loop,

integer_ring -> integer
-> rational
-> rational_field
-> categories/finite_fields
-> integer_ring

which is easily fixable. Yet after fixing it, I still get an
AttributeError from the integer <-> integer_ring loop:

$ python -q
>>> from sage.rings.integer_ring import ZZ
Traceback (most recent call last):
File "<python-input-0>", line 1, in <module>
from sage.rings.integer_ring import ZZ
File "sage/rings/integer_ring.pyx", line 1, in init sage.rings.integer_ring
r"""
File "sage/rings/integer.pyx", line 312, in init sage.rings.integer
cdef Parent the_integer_ring = integer_ring.ZZ
AttributeError: partially initialized module
'sage.rings.integer_ring' from
'/home/mjo/.../integer_ring.cpython-313-riscv64-linux-musl.so'
has no attribute 'ZZ' (most likely due to a circular import)

This has me confused. I'm certain I've imported ZZ from python before,
and I'm also pretty sure that the integer <-> integer_ring loop is not
new.

Has anything else changed? Is it just me? (This requires sagelib to be
installed as a python package via pip, meson, or a package manager; it
works fine from within a sage prompt.)

Antonio Rojas

unread,
Sep 24, 2025, 12:17:46 PM (8 days ago) Sep 24
to sage-devel
El miércoles, 24 de septiembre de 2025 a las 16:51:32 UTC+2, Michael Orlitzky escribió:

Has anything else changed? Is it just me? (This requires sagelib to be
installed as a python package via pip, meson, or a package manager; it
works fine from within a sage prompt.)

Can reproduce as far back as 10.4 (that's the oldest I can test without downgrading Python). But 10.6 and older used to give a different (quite uninformative) error:

In [1]: from sage.rings.integer_ring import ZZ
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
Cell In[1], line 1
----> 1 from sage.rings.integer_ring import ZZ

File /usr/lib/python3.13/site-packages/sage/rings/integer_ring.pyx:1, in init sage.rings.integer_ring (build/cythonized/sage/rings/integer_ring.c:21194)()
----> 1 r"""
     2 Ring `\ZZ` of Integers
     3  

File /usr/lib/python3.13/site-packages/sage/rings/integer.pyx:1, in init sage.rings.integer (build/cythonized/sage/rings/integer.c:62499)()
----> 1 r"""
     2 Elements of the ring `\ZZ` of integers
     3  

File /usr/lib/python3.13/site-packages/sage/rings/rational.pyx:76, in init sage.rings.rational (build/cythonized/sage/rings/rational.cpp:45244)()
    74 from sage.libs.gmp.pylong cimport mpz_set_pylong
    75 from sage.rings.integer cimport Integer, smallInteger
---> 76 from sage.rings.integer_ring import ZZ
    77 from sage.structure.coerce cimport coercion_model, is_numpy_type
    78 from sage.structure.element cimport Element

Nils Bruin

unread,
Sep 24, 2025, 12:50:40 PM (8 days ago) Sep 24
to sage-devel
This kind of problem has been around for a long time and it has been the case that the order in which imports get executed affects if circular import errors are raised. If the problem really was a circular import it shouldn't really matter in which order it happens: the cycle will always cause problems. So it seems it's just python being finicky -- or python having some special cases that allow it to handle some types of import cycles.

I don't know if this particular one already happened from the start but I do recall exactly this kind of thing being the issue.

In this particular case, it seems executing

import sage.rings.integer
import sage.rings.integer_ring

gets around the problem. It's of course why we have sage.all. In this case, sage.rings.all also works and would get you slightly less but probably still more than you want. The above example doesn't: sage.rings.integer is part of the cycle anyway.

It may well be that in the past you imported ZZ with this little workaround of including an auxiliary import.

Michael Orlitzky

unread,
Sep 24, 2025, 2:47:44 PM (8 days ago) Sep 24
to sage-...@googlegroups.com
On Wed, 2025-09-24 at 09:17 -0700, Antonio Rojas wrote:
> El miércoles, 24 de septiembre de 2025 a las 16:51:32 UTC+2, Michael
> Orlitzky escribió:
>
>
> Has anything else changed? Is it just me? (This requires sagelib to be
> installed as a python package via pip, meson, or a package manager; it
> works fine from within a sage prompt.)
>
>
> Can reproduce as far back as 10.4 (that's the oldest I can test without
> downgrading Python). But 10.6 and older used to give a different (quite
> uninformative) error:

Ok, thanks, good to know I guess. I'm still looking for
incontrovertible evidence that this used to work, but I'm trying not to
waste my whole day on it.

Michael Orlitzky

unread,
Sep 24, 2025, 3:03:08 PM (8 days ago) Sep 24
to sage-...@googlegroups.com
On Wed, 2025-09-24 at 09:50 -0700, Nils Bruin wrote:
> In this particular case, it seems executing
>
> import sage.rings.integer
> import sage.rings.integer_ring
>
> gets around the problem. It's of course why we have sage.all. In this case,
> sage.rings.all also works and would get you slightly less but probably
> still more than you want. The above example doesn't: sage.rings.integer is
> part of the cycle anyway.

Thanks, I also discovered this trick. I'm more alarmed by the
impression that it's new than anything else. Unless I stumble across a
smoking gun, I'll have to assume that my memory is wrong and I was
avoiding it by pure chance.

I thought https://github.com/sagemath/sage/pull/40443 would be a good
example, but the import of FiniteField() is what makes it possible to
import QQ in that case.
Reply all
Reply to author
Forward
0 new messages