Circular imports (again)

Discussion in 'Python' started by Frank Millman, Aug 9, 2010.

  1. Hi all

    I know the problems related to circular imports, and I know some of the
    techniques to get around them. However, I find that I bump my head into them
    from time to time, which means, I guess, that I have not fully understood
    how to organise my code so that I avoid them in the first place.

    It has just happened again. I have organised my code into three modules,
    each representing a fairly cohesive functional area of the overall
    application. However, there really are times when Module A wants to invoke
    something from Module B, ditto for B and C, and ditto for C and A.

    I can think of two workarounds. One is to place the import statement inside
    the function that actually requires it. It is therefore not executed when
    the module itself is imported, thereby avoiding the problem. It works, but
    breaks the convention that all imports should be declared at the top of the
    program.

    A second solution is to avoid invoking the other modules directly, but
    rather use global Queue.Queues to pass requests from one module to another.
    Again, it works, but adds complication, especially if the 'invoker' needs to
    get a return value.

    So I think my main question is, is this a symptom of a flaw in my approach,
    or is this something that all programmers bump into from time to time?

    If the former, I can expand on my current requirement if anyone would like
    to suggest a better approach. If the latter, is either of the above
    solutions preferred, or are there other techniques to get around the
    problem.

    Any suggestions will be appreciated.

    Thanks

    Frank Millman
    Frank Millman, Aug 9, 2010
    #1
    1. Advertising

  2. Frank Millman

    Carl Banks Guest

    On Aug 9, 6:19 am, "Frank Millman" <> wrote:
    > It has just happened again. I have organised my code into three modules,
    > each representing a fairly cohesive functional area of the overall
    > application. However, there really are times when Module A wants to invoke
    > something from Module B, ditto for B and C, and ditto for C and A.


    There's a dozen reasons why circular imports can go wrong. Can you
    describe the problem you're having getting them to work? If there's a
    traceback when you try to do it, cut-and-paste the traceback and
    relevant code here. If it's running, but you are not getting the
    behavior you expect, tell us what you expected to happen and what
    actually did.


    [snip]
    > So I think my main question is, is this a symptom of a flaw in my approach,
    > or is this something that all programmers bump into from time to time?


    I consider the need to resort to circular imports a red flag, not a
    manifest error. You say you are organizing the modules
    "functionally". I find that when I do that, I will occasionally get
    circular references, so I can believe you. I also find that in most
    such cases, reorganizing the modules according to "dependencies", so
    as to remove the circular import, makes it more confusing. Sometimes
    organizing by function makes more sense than organizing by dependency,
    and it's better to live with circular imports than to use a less-
    sensical organization.


    Carl Banks
    Carl Banks, Aug 9, 2010
    #2
    1. Advertising

  3. On Aug 9, 6:19 am, "Frank Millman" <> wrote:
    > It has just happened again. I have organised my code into three modules,
    > each representing a fairly cohesive functional area of the overall
    > application. However, there really are times when Module A wants to invoke
    > something from Module B, ditto for B and C, and ditto for C and A.


    There are a number of ways to avoid circular imports, in order of my own
    preference:

    1. Make common stuff a new module. So if A needs something from B, and
    vice versa, you must factor out the stuff and stick it in its own
    module. The fact that you have circular dependencies means that
    although things are cohesive, they are way too closely coupled.

    2. Instead of having A refer directly to something in B (which would
    cause a circular dependency, have the caller pass in as a parameter to
    the function in A, whatever is needed from B. This could be just a
    variable, complex object, or even a function or method. Take advantage
    of the fact that everything in Python is a first-class object.

    3. Take advantage of Python's dynamicism. Write an initializer function
    in A that allows you to tell it about B and C. In other words, you can
    pass B and C to some method in A and have it bind B and C to local
    attributes in A. Then you can call B and C's methods just fine from A
    since everything is looked up as it is called.
    Michael Torrie, Aug 9, 2010
    #3
    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.
Similar Threads
  1. Kiuhnm
    Replies:
    16
    Views:
    728
    Jonathan Mcdougall
    Jan 3, 2005
  2. Edward Diener

    Circular imports

    Edward Diener, May 19, 2004, in forum: Python
    Replies:
    2
    Views:
    356
    Edward Diener
    May 20, 2004
  3. circular imports

    , May 20, 2005, in forum: Python
    Replies:
    5
    Views:
    332
  4. Spencer Pearson
    Replies:
    7
    Views:
    281
    Spencer Pearson
    Sep 9, 2010
  5. Frank Millman
    Replies:
    5
    Views:
    656
    Frank Millman
    Mar 6, 2011
Loading...

Share This Page