Circular import problem

B

bvdp

I'm going quite nutty here with an import problem. I've got a fairly
complicated program (about 12,000 lines in 34 modules). I just made
some "improvements" and get the following error:

bob$ mma
Traceback (most recent call last):
File "/usr/local/bin/mma", line 55, in <module>
import MMA.main
File "/usr/local/share/mma/MMA/main.py", line 33, in <module>
import MMA.docs
File "/usr/local/share/mma/MMA/docs.py", line 34, in <module>
import MMA.grooves
File "/usr/local/share/mma/MMA/grooves.py", line 41, in <module>
import MMA.auto
File "/usr/local/share/mma/MMA/auto.py", line 35, in <module>
import MMA.parse
File "/usr/local/share/mma/MMA/parse.py", line 2052, in <module>
'AUTHOR': MMA.docs.docAuthor,
AttributeError: 'module' object has no attribute 'docs'

I can fix this by deleting a line in docs.py. Just take out the
"import MMA.grooves" and all works. What I really don't get is that in
the middle of this module which is now NOT loading "grooves.py" I have
a command to access a function in that module and it works.

Yes, grooves.py has an import docs.py. And there are lots of other
such imports in the program.

So, I have to assume that the error is being generated by some other
modules loading in the grooves.py stuff ... but really have no idea.

Is there anything I can do to trace though this and get it working
properly?

Oh, this is python 2.5.1 on Ubuntu Linux.

Thanks.
 
G

Gabriel Genellina

I'm going quite nutty here with an import problem. I've got a fairly
complicated program (about 12,000 lines in 34 modules). I just made
some "improvements" and get the following error:

bob$ mma
Traceback (most recent call last):
File "/usr/local/bin/mma", line 55, in <module>
import MMA.main
File "/usr/local/share/mma/MMA/main.py", line 33, in <module>
import MMA.docs
File "/usr/local/share/mma/MMA/docs.py", line 34, in <module>
import MMA.grooves
File "/usr/local/share/mma/MMA/grooves.py", line 41, in <module>
import MMA.auto
File "/usr/local/share/mma/MMA/auto.py", line 35, in <module>
import MMA.parse
File "/usr/local/share/mma/MMA/parse.py", line 2052, in <module>
'AUTHOR': MMA.docs.docAuthor,
AttributeError: 'module' object has no attribute 'docs'

I can fix this by deleting a line in docs.py. Just take out the
"import MMA.grooves" and all works. What I really don't get is that in
the middle of this module which is now NOT loading "grooves.py" I have
a command to access a function in that module and it works.

Yes, grooves.py has an import docs.py. And there are lots of other
such imports in the program.

So, I have to assume that the error is being generated by some other
modules loading in the grooves.py stuff ... but really have no idea.

Is there anything I can do to trace though this and get it working
properly?

See http://effbot.org/zone/import-confusion.htm
Try to move the circular references later in the code (maybe inside a
function, when it is required), or much better, refactor it so there is no
circularity.
 
B

bvdp

Seehttp://effbot.org/zone/import-confusion.htm
Try to move the circular references later in the code (maybe inside a
function, when it is required), or much better, refactor it so there is no
circularity.

Yes, thanks. I'd read that page before posting. Helpful.

But, I still don't understand how python can access a function in a
file I have NOT included. In this case, to get things to work, I DO
NOT "import MMA.grooves" but later in the module I access a function
with "xx=MMA.grooves.somefunc()" and it finds the function, and works
just fine. It shouldn't work.

I have tried to delay the import, and that does work. But, from a
stylistic view I really to like to have all my imports at the top of
the module. Maybe some old assembler/C habits on my part.
 
B

bvdp

Just as a bit of a followup, I have fixed the problem in my code. I
changed the order of some of the imports in some other modules.

What I was doing was more guesswork and good luck ... but it works. I
really wonder if there is a better way to figure these problems out.
Reading a few of the other discussions on the 'net about this it seems
that I'm not the 1st to get hit with the problem ... and the solutions
I find aren't any prettier than mine :)
 
G

Gabriel Genellina

Yes, thanks. I'd read that page before posting. Helpful.

But, I still don't understand how python can access a function in a
file I have NOT included. In this case, to get things to work, I DO
NOT "import MMA.grooves" but later in the module I access a function
with "xx=MMA.grooves.somefunc()" and it finds the function, and works
just fine. It shouldn't work.

That depends a bit on what is "MMA" and what is "grooves".
MMA.grooves means "look for an attribute named grooves inside MMA". If MMA
is a module, and MMA.grooves is a class/function defined inside the
module, you don't need to import it before using it.
But if MMA is a package, and MMA.grooves is a module inside that package,
you need to import it first (unless MMA/__init__.py does that already)
I have tried to delay the import, and that does work. But, from a
stylistic view I really to like to have all my imports at the top of
the module. Maybe some old assembler/C habits on my part.

Sure, it's considered good style.
 
B

bvdp

That depends a bit on what is "MMA" and what is "grooves".
MMA.grooves means "look for an attribute named grooves inside MMA". If MMA
is a module, and MMA.grooves is a class/function defined inside the
module, you don't need to import it before using it.
But if MMA is a package, and MMA.grooves is a module inside that package,
you need to import it first (unless MMA/__init__.py does that already)

In this case (and I should have been more clear) MMA is a package and
grooves is a module. It is working now, but before I moved other
imports around I was able to do the following:

1. NOT include MMA.gooves,
2. call the function MMA.grooves.somefunc()

and have it work. The point I was trying to make was that something in
my imports was causing the namespace to contain MMA.grooves.* when it
hadn't been imported in that module.

I suspect that my reordering effected some initialization of modules,
probably the creation of some classes. But that is a guess.

I've just used an empty __init__.py file. I will have to read up a bit
more on packages and see what advantage there is to import in that.
Sure, it's considered good style.

Which is considered good style? Loading at the top or loading when
needed?
 
G

greg

bvdp said:
before I moved other
imports around I was able to do the following:

1. NOT include MMA.gooves,
2. call the function MMA.grooves.somefunc()

and have it work.

The import doesn't necessarily have to be in the same module
where the attribute is used. The first time *any* module
does 'import MMA.grooves', a grooves attribute gets put
into MMA, which can be used by any module that has a
reference to MMA.

It's probably not a good idea to rely on this, though,
and better to put an explicit 'import MMA.grooves' into
every module that uses it. Importing something more than
once does no harm.
 
G

Gabriel Genellina

I've just used an empty __init__.py file. I will have to read up a bit
more on packages and see what advantage there is to import in that.

__init__.py is executed inside the package's namespace - whatever you
import/define there, is available later as packagename.zzz
Which is considered good style? Loading at the top or loading when
needed?

I mean, importing at the top of the module is the recommended practice.
See http://www.python.org/dev/peps/pep-0008/
I try only to import locally: a) when it is slow and not always needed,
and b) when the imported module is unrelated to the main purpose (e.g.
import traceback inside some exception handlers).
 
A

Alex Popescu

En Fri, 13 Jul 2007 13:24:57 -0300, bvdp <[email protected]> escribió:








That depends a bit on what is "MMA" and what is "grooves".
MMA.grooves means "look for an attribute named grooves inside MMA". If MMA
is a module, and MMA.grooves is a class/function defined inside the
module, you don't need to import it before using it.

I am a bit confused: I think the above should be:

if MMA.grooves in a class/function defined inside the module MMA, you
don't need to import the
class/function before using it, but only import the module MMA.

Am I wrong?

tia,

../alex
 
G

Gabriel Genellina

En Sun, 15 Jul 2007 08:49:54 -0300, Alex Popescu
I am a bit confused: I think the above should be:

if MMA.grooves in a class/function defined inside the module MMA, you
don't need to import the
class/function before using it, but only import the module MMA.

Am I wrong?

You are right, but we were talking about a slightly different scenario. To
make things clear:

1)
import MMA
xx=MMA.grooves.somefunc()

2)
import MMA.grooves
xx=MMA.grooves.somefunc()

If MMA is a module, containing a class named gooves, those two ways are
valid.
If MMA is a package, and grooves is a module contained in the package,
only the second one is valid (assuming the package has an empty
__init__.py, or does not import grooves itself)

The OP was asking why the second form worked fine for him for a while, but
stopped working after reordering some imports. And the answer (according
to "Greg") is: some other module imported MMA.grooves, and that put
grooves into MMA namespace, available for everyone else.
 
A

Alex Popescu

En Sun, 15 Jul 2007 08:49:54 -0300, Alex Popescu
<[email protected]> escribió:







You are right, but we were talking about a slightly different scenario. To
make things clear:

1)
import MMA
xx=MMA.grooves.somefunc()

2)
import MMA.grooves
xx=MMA.grooves.somefunc()

If MMA is a module, containing a class named gooves, those two ways are
valid.
If MMA is a package, and grooves is a module contained in the package,
only the second one is valid (assuming the package has an empty
__init__.py, or does not import grooves itself)

The OP was asking why the second form worked fine for him for a while, but
stopped working after reordering some imports. And the answer (according
to "Greg") is: some other module imported MMA.grooves, and that put
grooves into MMA namespace, available for everyone else.

Now, everything is 100% clear.

bests,

../alex
 

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,902
Latest member
Elena68X5

Latest Threads

Top