473,412 Members | 2,294 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,412 software developers and data experts.

FAQ 1.7.3 : How can I have modules that mutually import each other

Hi

I'm new to Python, I've read the FAQ but still can't get the following
simple example working:

# file main_mod.py:

global_string = 'abc'

def main():

import auxiliary_mod
instance = auxiliary_mod.ClassA()
instance.fun()
return

main()

# file auxiliary_mod.py:

class ClassA:

def fun(self):

import main_mod

print 'this is ClassA.fun() and global_string is ' +
main_mod.global_string

return

In words, the problem is: I've a main module which defines a global
variable and instantiates a class defined in a second module, and a
method of that class needs to access the global variable defined in the
main module.

When I run main_mod.py the method is executed twice:

this is ClassA.fun() and global_string is abc
this is ClassA.fun() and global_string is abc

How can I avoid this problem even in this simple example? If I move the
import main_mod statement to the outside of the definion of ClassA I
get an exception:

Traceback (most recent call last):
File "./main_mod.py", line 4, in ?
import auxiliary_mod
File "/manel/ewt/test/auxiliary_mod.py", line 4, in ?
import main_mod
File "/manel/ewt/test/main_mod.py", line 13, in ?
main()
File "/manel/ewt/test/main_mod.py", line 9, in main
instance = auxiliary_mod.ClassA()
AttributeError: 'module' object has no attribute 'ClassA'
As far as I can tell I'm following the technique suggested by Guido
himself to handle mutual imports:

"Guido van Rossum recommends avoiding all uses of from <module> import
...., and placing all code inside functions. Initializations of global
variables and class variables should use constants or built-in
functions only. This means everything from an imported module is
referenced as <module>.<name>."

[http://www.python.org/doc/faq/programming.html]

How can I get this simple example to work?

Thank you for any help in advance,

Mack

Jul 18 '05 #1
4 2171
MackS wrote:
Hi

I'm new to Python, I've read the FAQ but still can't get the following
simple example working:

# file main_mod.py:

global_string = 'abc'

def main():

import auxiliary_mod
instance = auxiliary_mod.ClassA()
instance.fun()
return

main()

# file auxiliary_mod.py:

class ClassA:

def fun(self):

import main_mod

print 'this is ClassA.fun() and global_string is ' +
main_mod.global_string

return

In words, the problem is: I've a main module which defines a global
variable and instantiates a class defined in a second module, and a
method of that class needs to access the global variable defined in the
main module.
[...] How can I get this simple example to work?


You suffer from a circular dependency issue. The general solution in
this case is to factor out code into a third module. In your case,
consider putting global_string or main() in a third module that you can
import from auxiliary_mod.

Reinhold
Jul 18 '05 #2
On 19 Mar 2005 12:05:18 -0800, "MackS" <ma***********@hotmail.com>
wrote:
Hi

I'm new to Python, I've read the FAQ but still can't get the following
simple example working:

# file main_mod.py:
global_string = 'abc'
def main():
import auxiliary_mod
instance = auxiliary_mod.ClassA()
instance.fun()
main()

# file auxiliary_mod.py:
class ClassA:
def fun(self):
import main_mod
print 'this is ClassA.fun() and global_string is ' +
main_mod.global_string

In words, the problem is: I've a main module which defines a global
variable and instantiates a class defined in a second module, and a
method of that class needs to access the global variable defined in the
main module.
Needs??? Sorry to be blunt, but this is an intrinsically ludicrous
concept, in *any* language. The whole idea of modules is (wait for it)
"modularity". "A imports B which imports A" is an utter nonsense.

When I run main_mod.py the method is executed twice:
Care needs to be taken in general with a module that is to be RUN as a
script as well as imported; for further details, and an explanation of
why your method is executed twice, see sample code at the end of my
post. Please note: I'm showing you this because it's something you
need to know about Python quite *independently* of the fubaristic
circular import thing.
How can I avoid this problem even in this simple example?
Don't have circular imports.
How can I get this simple example to work?


You shouldn't try. Refactor. NOTE: "executed once only" doesn't mean
that it is "working".

=== mainmod.py ===
global_string = 'abc'

def main():
import auxmod
instance = auxmod.ClassA()
instance.fun()
# don't need this: return

print "Statements are also EXECUTED when the module is imported."
print "Best to avoid statements with side-effects."
main()
print "Got the picture now?"

if __name__ == "__main__":
print "Being run as a script i.e. not imported."
main()
print "Done ..."

=== auxmod.py ===
trip_count = 0
class ClassA:
def fun(self):
global trip_count
trip_count += 1
saved_tc = trip_count
print 'ClassA.fun -- before importing mainmod; tc =',
trip_count
import mainmod
print 'ClassA.fun -- after importing mainmod; tc =',
trip_count, 'saved_tc =', saved_tc
print 'global_string is', mainmod.global_string
Jul 18 '05 #3
Circular import dependencies don't work well; depending
on the exact conditions they can leave you pulling your hair
out for hours. In your example, just pull the global variable
out into a third module and have both of your major
modules import and reference it from there.

In general, you should never have circular imports at
load time. There are three general ways of handling
the issue:

1. Redesign to eliminate the circular dependencies.
2. Put the classes with the circular dependencies in
the same module.
3. Load the backlinks at run time.

I may be old fashioned, but I put all of the import
statements at the top of the module. Putting them
into the middle of functions obscures the structure
of the code, at least to my eyes. I'd rather have them
all in one place.

I've got a Java package (Fit Library) that I'm porting
to Python that has a number of very nasty circular
import dependencies that I can't structure out easily:
they're fundamental to the functionality. I'm taking
the "load at run time" option, which works well since
the basic FIT package has a very competent dynamic
loader.

However, all of this is kind of advanced functionality.
Most applications don't require that kind of mess.

John Roth


"MackS" <ma***********@hotmail.com> wrote in message
news:11**********************@g14g2000cwa.googlegr oups.com...
Hi

I'm new to Python, I've read the FAQ but still can't get the following
simple example working:

# file main_mod.py:

global_string = 'abc'

def main():

import auxiliary_mod
instance = auxiliary_mod.ClassA()
instance.fun()
return

main()

# file auxiliary_mod.py:

class ClassA:

def fun(self):

import main_mod

print 'this is ClassA.fun() and global_string is ' +
main_mod.global_string

return

In words, the problem is: I've a main module which defines a global
variable and instantiates a class defined in a second module, and a
method of that class needs to access the global variable defined in the
main module.

When I run main_mod.py the method is executed twice:

this is ClassA.fun() and global_string is abc
this is ClassA.fun() and global_string is abc

How can I avoid this problem even in this simple example? If I move the
import main_mod statement to the outside of the definion of ClassA I
get an exception:

Traceback (most recent call last):
File "./main_mod.py", line 4, in ?
import auxiliary_mod
File "/manel/ewt/test/auxiliary_mod.py", line 4, in ?
import main_mod
File "/manel/ewt/test/main_mod.py", line 13, in ?
main()
File "/manel/ewt/test/main_mod.py", line 9, in main
instance = auxiliary_mod.ClassA()
AttributeError: 'module' object has no attribute 'ClassA'
As far as I can tell I'm following the technique suggested by Guido
himself to handle mutual imports:

"Guido van Rossum recommends avoiding all uses of from <module> import
..., and placing all code inside functions. Initializations of global
variables and class variables should use constants or built-in
functions only. This means everything from an imported module is
referenced as <module>.<name>."

[http://www.python.org/doc/faq/programming.html]

How can I get this simple example to work?

Thank you for any help in advance,

Mack


Jul 18 '05 #4
Needs??? Sorry to be blunt, but this is an intrinsically ludicrous
concept, in *any* language. The whole idea of modules is (wait for it) "modularity". "A imports B which imports A" is an utter nonsense.


There is such a thing called 'recursion'. Self-recursion is when
function x calls itself to execute the same action on a partial result
of its previous invocation. This technique is a natural expression of
what such ugly constructs as for and while are for in some programming
languages. Indirect recusion is when function x calls y, and function y
calls x. It is often happens in state automata.

A static equivalent of indirect recursion is dependencies between
declarations, when declaration x depends on y, and declaration y
depends on x. Imagine a design
of a literate programming environment, where both documentation and
text are structured, and either can contain the other. A natural design
for that is to have two modules, one implementing the parser for
documentation, the other implementing the parser for code, each
referencing the other so that both parsers can call each other when
they need to switch context.

In a well-designed programming language, circular intermodule
dependencies are normal, because this is a natural high-level
abstraction to express such relations. Because of primitive
implementation of modular system in Python, circular dependencies are
not possible, and things which are normally done automatically in a
higher-level language, need to be coded manually in Python.

In particular, to bypass this deficiency of Python for a problem
similar to one described above, one has to define base classes for each
of the two parsers, and make the implementations depend on the other
implementation's base class, not on itself, thus splitting the
interface and the implementation where it is not only unnecessary but
outright wrong if clean design is taken into consideration.

I'd wish a cleaner and more consistent implementation of packages
existed in Python; but unfortunately too many things in current Python
are far from being on the level a modern programming language (such as
Common Lisp, for example) demands.

David Tolpin
http://davidashen.net/

Jul 18 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Tobiah | last post by:
Hi, If I write a module for general purpose use that needs say, 'sys', 'os', 're' etc... and I import those modules from within my module, does this cause inefficiency when an existing program...
5
by: Pekka Niiranen | last post by:
Hi there, I have two scripts. The first "main.py" sets some variables and then imports another called "gen.py". The idea is to provide "main.py" that defines some paths, variables etc. without...
31
by: N.Davis | last post by:
I am very new to Python, but have done plenty of development in C++ and Java. One thing I find weird about python is the idea of a module. Why is this needed when there are already the ideas of...
2
by: icoba | last post by:
I have the following code: A.py ==== from B import B class R: def __str__(self): return "hello world"
0
by: David Rose | last post by:
I have an existing asp.net web application which contains several user controls. Some of these user controls contain other user controls (generic controls) which are located in a subdirectory. Now...
6
by: AndyL | last post by:
Hi, is there any way to specify the path to modules within import statement (like in Java)? For instance: "import my.path.module" would load module from ../my/path/module.py? Thx, A.
6
by: PenguinPig | last post by:
Dear All I have register a 3rd's DLL into my pc, and I can create an instance by using CreateObject in ASP page, eg. set obj = CreateObject("3rdDLLName"); And it contains several methods such...
4
by: Christoph Zwerschke | last post by:
I'm currently investigating a problem that can hit you in TurboGears when Kid template modules are reloaded in the background, because in certain situations, global variables suddenly are set to...
3
by: Mohamed Yousef | last post by:
Hello , The problem I'm asking about is how can imported modules be aware of other imported modules so they don't have to re-import them (avoiding importing problems and Consicing code and...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.