Cycles between package imports

M

Martin Blais

Hi

I'm a tad confused over a problem involving cycles between
packages.

Assume the following sets of files::

driver.py
a/__init__.py
a/alice.py
b/__init__.py
b/bob.py

Basically, two packages a and b. Driver simply imports one of the
two. This is the file that gets run::

,---- (driver.py)
|
| import a.alice
|
`----

The package initialization files (__init__.py) both contain
nothing. a.alice imports b.bob, and b.bob imports a.alice.

The following works fine:

,---- (a/alice.py)
|
| import b.bob
|
`----

,---- (b/bob.py)
|
| import a.alice
|
`----


However, if I change b/bob.py to import using "from" syntax, i.e.:

,---- (b/bob.py)
|
| from a import alice
|
`----

It does not work anymore::

Traceback (most recent call last):
File "driver.py", line 3, in ?
import a.alice
File "/tmp/experiments/import-cycle/a/alice.py", line 9, in ?
import b.bob
File "/tmp/experiments/import-cycle/b/bob.py", line 9, in ?
from a import alice
ImportError: cannot import name alice


So cycles between packages do not behave as cycles between
modules--there is a subtlety.

At the time that b/bob.py attempts to import a.alice, a.alice is
still being imported (i.e. executed), and there is a difference
between

import a.alice

and

from a import alice


I don't see why the reference to module a.alice could not be
available via the "from" syntax, even if it is still incompletely
initialized at the time of import.

Can anyone shed some light onto this? Is there a rule for
determining when a module becomes available to import from a
package using the "from" syntax?
 
J

John Roth

Martin said:
Hi

I'm a tad confused over a problem involving cycles between
packages.

[lengthy example snipped]
I don't see why the reference to module a.alice could not be
available via the "from" syntax, even if it is still incompletely
initialized at the time of import.

Can anyone shed some light onto this? Is there a rule for
determining when a module becomes available to import from a
package using the "from" syntax?

It's really easy to see if you trace out, in detail, the exact
order in which things happen and when each object is initialized and
shows up in the respective module's namespace.

The general rule is: don't do that. It doesn't work, and the
hoops you have to go through to force it to work are so
complex and bizzare that they're not worth it. Redesign
the modules so you don't have cyclic dependencies.

John Roth
 
M

Martin Blais

Martin said:
Hi

I'm a tad confused over a problem involving cycles between
packages.

[lengthy example snipped]
I don't see why the reference to module a.alice could not be
available via the "from" syntax, even if it is still incompletely
initialized at the time of import.

Can anyone shed some light onto this? Is there a rule for
determining when a module becomes available to import from a
package using the "from" syntax?

It's really easy to see if you trace out, in detail, the exact
order in which things happen and when each object is initialized and
shows up in the respective module's namespace.

No it's not, at least I don't see it. The order in which the symbols
appear is different whether you're using the simple "import" form or
the "from ... import" form. This is exactly what the question is
about.


The general rule is: don't do that. It doesn't work, and the
hoops you have to go through to force it to work are so
complex and bizzare that they're not worth it. Redesign
the modules so you don't have cyclic dependencies.

This is a matter completely aside the question. Whether it's worth it
or not depends on the specific case --not included in the example--
and in the case where it shows up in my code, removing the cycle
actually made sense (it does, most of the time, but not always).

Thanks.
cheers,
 
L

Lawrence D'Oliveiro

"Martin Blais said:
This is a matter completely aside the question.

No it isn't. I agree with John Roth.
Whether it's worth it
or not depends on the specific case --not included in the example--
and in the case where it shows up in my code, removing the cycle
actually made sense (it does, most of the time, but not always).

See, even you are unable to come up with an example where a cyclic
import makes sense.

In general, the complications they introduce are simply not worth it.
This was discovered decades ago, during the development of languages
like Ada and Modula-2 which could do automatic initialization and
finalization of library modules arranged by the compiler/linker system.
 
M

Martin Blais

No it isn't. I agree with John Roth.

See below.

See, even you are unable to come up with an example where a cyclic
import makes sense.

This is irrelevant. I'm not interested in discussing nor debating
the merits of prohibiting or allowing cyclic imports with you nor with
anybody else, you're wasting your time.

The fact of the matter is that Python DOES allow cyclic imports, and
the way that they behave depends on the particular syntax used to
perform the import. This very specific particular item is what the
original question was about. If you want to discuss whether Python
should disallow cyclic imports to prevent users to using them, please
start your own thread.

cheers,

In general, the complications they introduce are simply not worth it.

"worth it". Subjective. Whatever.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top