Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Cyclic imports

Reply
Thread Tools

Cyclic imports

 
 
James
Guest
Posts: n/a
 
      06-27-2008
Hi all,
I'm looking for some advice dealing with cyclic, cross-package
imports.

I've created the following demo file structure:
../a/__init__.py
../a/a.py
../b/__init__.py
../b/b.py
../main.py

a.py imports a class from b.py and vice versa, and main.py imports
them both.

However, because a.py has not been completely read by the time it gets
to the:
from b import b
line, the
from a import a
line in b.py fails with an import error (stack trace at the end).

I hope that's clear: basically, because of the cyclic import, I see
incomplete modules which can't be imported.

Can I have this module hierarchy in some other way?

Thanks,
James

Stack trace from example:
File "main.py", line 1, in <module>
from a import a
File "/Users/james/tmp/python/a/a.py", line 1, in <module>
from b import b
File "/Users/james/tmp/python/b/b.py", line 1, in <module>
from a import a
ImportError: cannot import name a
 
Reply With Quote
 
 
 
 
Dan Bishop
Guest
Posts: n/a
 
      06-27-2008
On Jun 26, 10:40*pm, James <rent.lupin.r...@gmail.com> wrote:
> Hi all,
> I'm looking for some advice dealing with cyclic, cross-package
> imports.
>
> I've created the following demo file structure:
> ./a/__init__.py
> ./a/a.py
> ./b/__init__.py
> ./b/b.py
> ./main.py
>
> a.py imports a class from b.py and vice versa, and main.py imports
> them both.
>
> However, because a.py has not been completely read by the time it gets
> to the:
> from b import b
> line, the
> from a import a
> line in b.py fails with an import error (stack trace at the end).
>
> I hope that's clear: basically, because of the cyclic import, I see
> incomplete modules which can't be imported.
>
> Can I have this module hierarchy in some other way?


# a.py
import b
# refer to b.b

# b.py
import a
# refer to a.a
 
Reply With Quote
 
 
 
 
James
Guest
Posts: n/a
 
      06-27-2008
> # a.py
> import b
> # refer to b.b
>
> # b.py
> import a
> # refer to a.a


Thanks Dan, but that still doesn't work for me I'm afraid...

I renamed the modules avoid name overloading -- a.py is now:
import b

class A():
print('b.b_mod:', b.b_mod)

b is now defined, but b.b_mod isn't:
File "main.py", line 1, in <module>
from a import a_mod
File "/Users/james/tmp/python/a/a_mod.py", line 3, in <module>
class A():
File "/Users/james/tmp/python/a/a_mod.py", line 4, in A
print('b.b_mod:', b.b_mod)
AttributeError: 'module' object has no attribute 'b_mod'

I must be missing something here - I've tried adding the modules to
__all__ in __init__.py but that didn't help either.

James
 
Reply With Quote
 
Carl Banks
Guest
Posts: n/a
 
      06-27-2008
On Jun 27, 12:58 am, James <rent.lupin.r...@gmail.com> wrote:
> > # a.py
> > import b
> > # refer to b.b

>
> > # b.py
> > import a
> > # refer to a.a

>
> Thanks Dan, but that still doesn't work for me I'm afraid...
>
> I renamed the modules avoid name overloading -- a.py is now:
> import b
>
> class A():
> print('b.b_mod:', b.b_mod)
>
> b is now defined, but b.b_mod isn't:
> File "main.py", line 1, in <module>
> from a import a_mod
> File "/Users/james/tmp/python/a/a_mod.py", line 3, in <module>
> class A():
> File "/Users/james/tmp/python/a/a_mod.py", line 4, in A
> print('b.b_mod:', b.b_mod)
> AttributeError: 'module' object has no attribute 'b_mod'
>
> I must be missing something here - I've tried adding the modules to
> __all__ in __init__.py but that didn't help either.



The above print statement runs at module import time, so you're seeing
something that might not be an issue in functioning code.

For instance, if you rewrite A like the following:

class A(object):
def print_b(self):
print('b.b_mod:', b.b_mod)

If you call the print_b method from outside the module (say, from
main.py), it should work.


What lessons did we learn here?

Be aware of the difference between code that runs at module import
time, and code that runs after the module is imported.

In code that runs after the module has been imported (basically
anything defined in a function that isn't called by code that runs at
module time), you can expect the variables defined in the imported
module to be available.

In code that runs at module import time, there is no such guarantee,
so you have to arrange your modules so that code that depends on
another module is run after the dependent module. (One common time
where this happens is when subclassing a class from another module:
the module with the base class needs to run first.)

If you have circular imports involved, making sure the modules import
in a certain order can be quite hairy. (Faced with this problem, I
found it necessary to write an import hook to pre-import certain
modules.)


Carl Banks
 
Reply With Quote
 
James
Guest
Posts: n/a
 
      06-27-2008
> In code that runs after the module has been imported (basically
> anything defined in a function that isn't called by code that runs at
> module time), you can expect the variables defined in the imported
> module to be available.
>
> If you have circular imports involved, making sure the modules import
> in a certain order can be quite hairy. *(Faced with this problem, I
> found it necessary to write an import hook to pre-import certain
> modules.)


Ok, thanks for all the advice: I now have the class architecture I was
looking for, by using much less specific imports, as Dan originally
suggested.

Re-factoring the use of partially loaded modules into functions wasn't
an option for me, unfortunately, as the classes were being used as
super classes or class variables. So, the code is a bit more verbose
than before, but works!

James
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Dynamic imports + relative imports in Python 3 zildjohn01 Python 0 02-22-2011 05:24 PM
Imports System.Data or Imports System.Data.SqlClient? Albert ASP .Net 4 07-10-2008 09:00 AM
The imp module and cyclic imports Matthias Kramm Python 2 11-27-2005 01:03 PM
How the compiler deals with cyclic static initialization Hongzheng Wang Java 1 12-02-2003 01:28 PM
Cyclic object graph question Laird Nelson Java 2 10-10-2003 07:53 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57