I have a rather fat module that represents a document parser --
inline elements, block elements, and the like. Now I want to split
it into many modules to make everything more manageable.
But at the moment I don't see how to avoid cyclic imports: A
document element A, which is represented my module parser.A, may
contain the element B, as defined in parser.B. And vice versa. So
both modules must import each other, as far as I can see.
I know that cyclic imports work in Python under certain
circumstances. Can anyone refer me to a page which explains *when*
this works? Because at least once, the imported module was not
"finished" and thus largely unusual.
Thank you!
Tschö,
Torsten.
--
Torsten Bronger, aquisgrana, europa vetus
Jabber ID: bro...@jabber.org
(See http://ime.webhop.org for further contact info.)
> I know that cyclic imports work in Python under certain
> circumstances. Can anyone refer me to a page which explains when
> this works?
I don't know of a specific URL offhand.
Cyclic imports are not a problem by themselves, but cyclic definitions are.
Thus:
# a.py
import b
x = 1
# b.py
import a
x = 2
works fine, but:
# a.py
import b
x = 1
# b.py
import a
x = a.x + 1 # circular definition
does not.
Jeffrey
Jeffrey Froman writes:
> [...]
>
> Cyclic imports are not a problem by themselves, but cyclic
> definitions are. Thus:
>
> # a.py
> import b
> x = 1
>
> # b.py
> import a
> x = 2
>
> works fine, but:
>
> # a.py
> import b
> x = 1
>
> # b.py
> import a
> x = a.x + 1 # circular definition
>
> does not.
Okay, thanks, but after some own investigations, I think that the
clever bit is somewhere else.
The above works if you call a.py as the main program, because then
a.py is not yet loaded as such when "import a" is executed. So a.py
gets executed twice, once by "import a", and once after the whole
import thing as the main program.
Actually, there seems to be only one case that is dangerous: If you
import a module cyclicly, it may be that you only get its name
imported but this name points to a yet empty module. Then, you must
not refer to things in it while the current module itself is
executed. But you may well refer to things in it from functions or
methods, because they are called much later, when the whole bunch of
modules is already completely loaded and populated.
Consequently, "from a import x" also fails if a is incomplete.
So, the last question is: Under which circumstances does this
happen? It happens when you import a module which imports (directly
or indictly) the current module and which comes before the current
module in the import order while the program runs.
If you don't rely on imported things at top-level code (but only in
functions and methods which in turn must not be called from the
top-level), everything is fine.
Can anybody confirm that this is correct?
> So, the last question is: Under which circumstances does this
> happen? It happens when you import a module which imports (directly
> or indictly) the current module and which comes before the current
> module in the import order while the program runs.
>
> If you don't rely on imported things at top-level code (but only in
> functions and methods which in turn must not be called from the
> top-level), everything is fine.
>
> Can anybody confirm that this is correct?
Imports are pretty straightforward really. Just remember the following:
'import' and 'from xxx import yyy' are executable statements. They execute
when the running program reaches that line.
If a module is not in sys.modules, then an import creates the new module
entry in sys.modules and then executes the code in the module. It does not
return control to the calling module until the execution has completed.
If a module does exist in sys.modules then an import simply returns that
module whether or not it has completed executing. That is the reason why
cyclic imports may return modules which appear to be partly empty.
Finally, the executing script runs in a module named __main__, importing
the script under its own name will create a new module unrelated to
__main__.
Take that lot together and you shouldn't get any surprises when importing
modules.