circular import Module

Discussion in 'Python' started by ajikoe@gmail.com, Jun 8, 2005.

  1. Guest

    Hello,

    I have two modules (file1.py and file2.py)
    Is that ok in python (without any weird implication) if my module
    import each other. I mean in module file1.py there exist command import
    file2 and in module file2.py there exist command import file1?

    This is not working in C#.

    pujo
    , Jun 8, 2005
    #1
    1. Advertising

  2. Hi !

    > Circular import does not work on module level, but you can
    > import the module in a method:
    >
    > file1.py:
    > import file2
    > ....
    >
    >
    > file2.py:
    > # import file1 # Does not work!
    > def foo():
    > import file1 # Does work


    Cool idea !

    It works on local namespaces, wich dont cause trouble to the whole program.

    +1


    --
    Douglas Soares de Andrade
    http://douglasandrade.cjb.net - dsa at unilestemg.br
    UnilesteMG - www.unilestemg.br
    ICQ, MSN = 76277921, douglas at tuxfamily.org
    Douglas Soares de Andrade, Jun 8, 2005
    #2
    1. Advertising

  3. Am Wed, 08 Jun 2005 01:11:50 -0700 schrieb :

    > Hello,
    >
    > I have two modules (file1.py and file2.py)
    > Is that ok in python (without any weird implication) if my module
    > import each other. I mean in module file1.py there exist command import
    > file2 and in module file2.py there exist command import file1?
    >
    > This is not working in C#.


    Circular import does not work on module level, but you can
    import the module in a method:

    file1.py:
    import file2
    .....


    file2.py:
    # import file1 # Does not work!
    def foo():
    import file1 # Does work

    HTH,
    Thomas

    --
    Thomas Güttler, http://www.thomas-guettler.de/
    Thomas Guettler, Jun 8, 2005
    #3
  4. Josef Meile Guest

    >>Circular import does not work on module level, but you can
    >>import the module in a method:
    >>
    >>file1.py:
    >>import file2
    >>....
    >>
    >>
    >>file2.py:
    >># import file1 # Does not work!
    >>def foo():
    >> import file1 # Does work

    >
    >
    > Cool idea !
    >
    > It works on local namespaces, wich dont cause trouble to the whole program.
    >
    > +1

    Yes, I also think is a good solution. Once I needed to do something like
    that and ended by writting a third module with the shared functions that
    the two conflicting modules needed. At that time I already knew that one
    could import modules from functions; however, I didn't come up with that
    solution :-(

    Regards,
    Josef
    Josef Meile, Jun 8, 2005
    #4
  5. That's the only way out I found with some module import problem using code
    generated by wxDesigner.


    Josef Meile wrote:

    >>>Circular import does not work on module level, but you can
    >>>import the module in a method:
    >>>
    >>>file1.py:
    >>>import file2
    >>>....
    >>>
    >>>
    >>>file2.py:
    >>># import file1 # Does not work!
    >>>def foo():
    >>> import file1 # Does work

    >>
    >>
    >> Cool idea !
    >>
    >> It works on local namespaces, wich dont cause trouble to the whole
    >> program.
    >>
    >> +1

    > Yes, I also think is a good solution. Once I needed to do something like
    > that and ended by writting a third module with the shared functions that
    > the two conflicting modules needed. At that time I already knew that one
    > could import modules from functions; however, I didn't come up with that
    > solution :-(
    >
    > Regards,
    > Josef
    Philippe C. Martin, Jun 8, 2005
    #5
  6. Greg Ewing Guest

    Thomas Guettler wrote:

    > file1.py:
    > import file2
    > ....
    >
    > file2.py:
    > # import file1 # Does not work!


    Actually, that *will* work as long as you don't
    try to use anything from file1 until it has finished
    being loaded.

    What won't work is

    file2.py:
    from file1 import somename

    because somename won't yet have been defined in
    file1 at the time file2 is imported.

    --
    Greg Ewing, Computer Science Dept,
    University of Canterbury,
    Christchurch, New Zealand
    http://www.cosc.canterbury.ac.nz/~greg
    Greg Ewing, Jun 9, 2005
    #6
  7. Magnus Lycka Guest

    wrote:
    > Hello,
    >
    > I have two modules (file1.py and file2.py)
    > Is that ok in python (without any weird implication) if my module
    > import each other. I mean in module file1.py there exist command import
    > file2 and in module file2.py there exist command import file1?


    Even if it works, it gives you a hint of a design
    problem that might come back and bite you later.

    If file1 depends on file2 *and* vice versa, it seems
    those two modules are tightly coupled. Perhaps they
    should be one module rather than two, or perhaps
    some redesign should be made to untangle this cycle.

    It happens that old Java programmers make one module
    per class when they start using Python. That's more
    or less equivalent of never using more than 8.3
    characters in filenames in modern operating systems,
    or to make a detour on your way to work because there
    used to be a fence blocking the shortest way a long
    time ago... :)

    Due to the cycle, you can never use file1 without
    file2 or vice versa. Why do you then want it to be
    two different modules instead of one?

    As others noted, you can usually fix your cycle problems
    by importing in a local scope, but just because you can,
    it doesn't mean that you should...
    Magnus Lycka, Jun 10, 2005
    #7
  8. On Friday 10 June 2005 07:27 am, Magnus Lycka wrote:
    > wrote:
    > > I have two modules (file1.py and file2.py)
    > > Is that ok in python (without any weird implication) if my module
    > > import each other. I mean in module file1.py there exist command import
    > > file2 and in module file2.py there exist command import file1?

    >
    > Even if it works, it gives you a hint of a design
    > problem that might come back and bite you later.
    >
    > If file1 depends on file2 *and* vice versa, it seems
    > those two modules are tightly coupled. Perhaps they
    > should be one module rather than two, or perhaps
    > some redesign should be made to untangle this cycle.


    True in principle, but what if the resulting module is 1000 lines long?

    It doesn't happen often, because python programs don't usually
    get that complicated (e.g. lots of tightly interacting classes), but there
    are enough exceptions to make it seem desireable to have modules
    divided only for readability (i.e. logically the same module).

    I can only think of one way to pull this off at present, though,
    and that is to create a package:

    big_package/
    __init__.py
    mod1.py
    mod2.py
    mod3.py

    where __init__.py looks something like:

    from mod1 import *
    from mod2 import *
    from mod3 import *

    Then you treat "big_package" as the module to import. You'll
    still have problems with names that need to be global to all three
    modules (I think they'd have to be in __init__.py or possibly in
    mod1 in order to work correctly), but it's pretty close.


    --
    Terry Hancock ( hancock at anansispaceworks.com )
    Anansi Spaceworks http://www.anansispaceworks.com
    Terry Hancock, Jun 11, 2005
    #8
  9. Greg Ewing Guest

    Magnus Lycka wrote:
    > Due to the cycle, you can never use file1 without
    > file2 or vice versa. Why do you then want it to be
    > two different modules instead of one?


    Perhaps because it would then be too big and
    unwieldy to maintain?

    Sometimes there are legitimate reasons for
    mutually-dependent modules.

    --
    Greg Ewing, Computer Science Dept,
    University of Canterbury,
    Christchurch, New Zealand
    http://www.cosc.canterbury.ac.nz/~greg
    Greg Ewing, Jun 14, 2005
    #9
  10. Magnus Lycka Guest

    Greg Ewing wrote:
    > Magnus Lycka wrote:
    >
    >> Due to the cycle, you can never use file1 without
    >> file2 or vice versa. Why do you then want it to be
    >> two different modules instead of one?

    >
    > Perhaps because it would then be too big and
    > unwieldy to maintain?
    >
    > Sometimes there are legitimate reasons for
    > mutually-dependent modules.


    Agreed, but I think it's important to think about
    the design if a chunk of code gets that big. Most
    of the time, things can be organized differently,
    and there will be maintenance gains from this. If
    you have mutual dependenices between two modules,
    they still have to be maintained as a unit. You
    can't disregard one when you modify the other. To
    achieve looser (and prefereably not mutual)
    dependencies between separate modules both makes
    it easier to maintain the modules and more likely
    that we will be able to reuse them in other contexts.

    Sure, there simple are tricks you can use to get away
    with mutual import dependencies, but if I ran into a
    mutual dependency between two Python modules, I would
    first think about their design and try to resolve this
    dependency issue. I probably wouldn't use a trick such
    as import in a local scope unless I was in a hurry and
    needed a quick fix while I was considering a proper
    design. (I might then be lazy and not resolve the
    design problem, but it would continue to disturb me...)

    Composition and inheritance might be used to break
    out parts of code that doesn't have dependencies to
    the rest of the code. There are all sorts of design
    pattern that can resolve mutual dependencies. I often
    use callbacks to get away from mutual dependencies.

    E.g.

    class Adder:
    def __init__(self, x, y, callback):
    self.x = x
    self.y = y
    self.callback = callback

    def calc(self):
    result = self.x + self.y
    self.callback(result)

    class Manager:
    def add(self, x, y):
    b = B(x, y, self.show)
    b.calc()

    def show(self, value):
    print value

    This is a silly example of course. Adder.calc could simply
    have returned the result, but I don't have time to construct
    anything elaborate now. The point I want to show is that
    by passing in a callable from Manager to Adder, Adder
    instances can call certain methods in particular Manager
    instanes without any dependencies to the module where Manager
    lives. It just needs to know what kind of parameters it should
    supply to the callable it was passed.

    Martin Fowler's book Refactoring shows a lot of examples
    that are useful when code grows and needs to be divided
    into smaller chunks. His examples and ideas revolve around
    Java and C++ though, and it's often much simpler in Python.
    Magnus Lycka, Jun 14, 2005
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.

Share This Page