Get importer module from imported module

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • dody suria wijaya

    #1

    Get importer module from imported module


    I found this problem when trying to split a module into two.
    Here's an example:

    ==============
    #Module a (a.py):
    from b import *
    class Main: pass
    ==============

    ==============
    #Module b (b.py)
    def How():
    Main_instance = module_a.Main()
    return Main_instance
    ==============
    [color=blue]
    > import a
    > a.How()[/color]


    the problem would show at How() function. I have been unable
    to get variable pointing to module a from inside module b.
    In short, I need to have a variable pointing to the module
    whose importing me.


    --
    dody s wijaya <dodysw@gmail.c om>, YM: dody, [36932B53]

  • Duncan Booth

    #2
    Re: Get importer module from imported module

    dody suria wijaya wrote:
    [color=blue]
    >
    > I found this problem when trying to split a module into two.
    > Here's an example:
    >
    >============ ==
    > #Module a (a.py):
    > from b import *
    > class Main: pass
    >============ ==
    >
    >============ ==
    > #Module b (b.py)
    > def How():
    > Main_instance = module_a.Main()
    > return Main_instance
    >============ ==
    >[color=green]
    >> import a
    >> a.How()[/color]
    >
    >
    > the problem would show at How() function. I have been unable
    > to get variable pointing to module a from inside module b.
    > In short, I need to have a variable pointing to the module
    > whose importing me.
    >
    >[/color]

    'import a' will let you reference module 'a', unless 'a' was invoked as a
    script in which case you would need 'import __main__'.

    #Module b (b.py)
    import a
    def How():
    Main_instance = a.Main()
    return Main_instance

    But: keep in mind that all statements (except 'global') are executable in
    Python, so you must not call How() until after the Main class has actually
    been created. This is one reason why it is generally safer to import a
    module and do the lookup when you need it instead of using 'from
    amodule import *' which can only get at the names which exist at the time
    it is executed.

    A better solution would be to structure your code so that your modules
    don't have any mutual dependencies. If your function 'How()' is in module b
    then just call 'b.How()' wherever you use it and lose the import of 'b'
    from 'a' altogether.

    Comment

    • dody suria wijaya

      #3
      Re[2]: Get importer module from imported module

      Thank you for such a quick reply. There were some details I
      had left behind related to my case that I guess would now
      need to be told to better illustrate the problem.

      I have many different module of "a", let's called it a1, a2 ...
      a100, and there is only one module "b". Here's a better
      example (and using some of your tips):

      #Module a1
      import b
      class Main(b.Basic): pass

      #Module a2
      import b
      class Main(b.Basic): pass

      #Module a3
      import b
      class Main(b.Basic): pass

      ..
      ..
      ..

      #Module b
      class Basic: pass
      class SaltyMixIn: pass
      class SugaryMixIn: pass
      def Salty():
      class Food(SaltyMixIn ,module_importi ng_me.Main): pass
      return Food()
      def Sweet():
      class Food(SugaryMixI n,module_import ing_me.Main): pass
      return Food()

      #Module c
      import sys
      food_no = sys.argv[1]
      m = __import__(food _no)
      goodie = m.Salty()


      "import a" inside b would not solve the problem, since there
      are many "module a" and module b does not know beforehand
      which module had imported it. I could, say, put these
      additional lines on all "module a" (which I previously had
      and worked):

      #Module a1
      import b
      class Main(b.Basic): pass
      class Salty(SaltyMixI n,Main): pass # new
      class Sweet(SaltyMixI n,Main): pass # new


      but dislike it for personal taste; code dupes (there could
      be a lot of food flavouring), and sheer messiness.


      --
      dody suria wijaya
      YahooMsgr ID: dody

      Monday, February 7, 2005, 6:10:14 PM, you wrote:

      DB> dody suria wijaya wrote:
      [color=blue][color=green]
      >>
      >> I found this problem when trying to split a module into two.
      >> Here's an example:
      >>
      >>============= =
      >> #Module a (a.py):
      >> from b import *
      >> class Main: pass
      >>============= =
      >>
      >>============= =
      >> #Module b (b.py)
      >> def How():
      >> Main_instance = module_a.Main()
      >> return Main_instance
      >>============= =
      >>[color=darkred]
      >>> import a
      >>> a.How()[/color]
      >>
      >>
      >> the problem would show at How() function. I have been unable
      >> to get variable pointing to module a from inside module b.
      >> In short, I need to have a variable pointing to the module
      >> whose importing me.
      >>
      >>[/color][/color]

      DB> 'import a' will let you reference module 'a',
      DB> unless 'a' was invoked as a
      DB> script in which case you would need 'import __main__'.

      DB> #Module b (b.py)
      DB> import a
      DB> def How():
      DB> Main_instance = a.Main()
      DB> return Main_instance

      DB> But: keep in mind that all statements (except
      DB> 'global') are executable in
      DB> Python, so you must not call How() until after the Main class has actually
      DB> been created. This is one reason why it is
      DB> generally safer to import a
      DB> module and do the lookup when you need it instead of using 'from
      DB> amodule import *' which can only get at the names which exist at the time
      DB> it is executed.

      DB> A better solution would be to structure your code so that your modules
      DB> don't have any mutual dependencies. If your
      DB> function 'How()' is in module b
      DB> then just call 'b.How()' wherever you use it and lose the import of 'b'
      DB> from 'a' altogether.

      Comment

      • Duncan Booth

        #4
        Re: Re[2]: Get importer module from imported module

        dody suria wijaya wrote:
        [color=blue]
        > "import a" inside b would not solve the problem, since there
        > are many "module a" and module b does not know beforehand
        > which module had imported it.[/color]

        Ok, I understand now what you are trying to achieve, but there isn't any
        concept relating a module back to the first module which tried to import
        it. Instead you'll have to specify the relationship yourself.

        How about this:
        [color=blue]
        > #Module c[/color]
        import sys
        food_no = sys.argv[1]
        m = __import__(food _no)
        goodie = b.Salty(m)
        [color=blue]
        > #Module b[/color]
        ....
        def Salty(module):
        class Food(SaltyMixIn ,module.Main): pass
        return Food()
        ....

        In fact, it looks like the importing isn't really something module c should
        be concerned about. I haven't tested the following code (so it will have
        bugs), but it should give you some ideas. It remembers classes it has
        created so as not to duplicate them, and it also gives each class a
        sensible name.
        [color=blue]
        > #Module c[/color]
        import sys
        food_no = sys.argv[1]
        goodie = b.Salty(food_no )
        [color=blue]
        > #Module b[/color]
        ....
        import new
        Classes = {}

        def makeFood(classn ame, food, mixin):
        m = __import__(food )
        main = m.Main
        if (mixin, main) in Classes:
        return Classes[mixin, main]()

        newclass = new.classobj(cl assname + '_' + food, (mixin, main), {})
        Classes[mixin, main] = newclass
        return newclass


        def Salty(food):
        return makeFood('Salty ', food, SaltyMixIn)
        ....

        Comment

        • dody suria wijaya

          #5
          Re[4]: Get importer module from imported module

          Yup, Got it.

          New problem though. On line:

          newclass = new.classobj(cl assname + '_' + food, (mixin, main), {})

          received "TypeError: metaclass conflict: the metaclass of a
          derived class must be a (non-strict) subclass of the
          metaclasses of all its bases". This had not happened when
          was written using 'normal' style like:

          class (SaltyMixIn, Main): pass

          --
          dody suria wijaya
          YahooMsgr ID: dody

          Monday, February 7, 2005, 7:20:14 PM, you wrote:

          DB> dody suria wijaya wrote:
          [color=blue][color=green]
          >> "import a" inside b would not solve the problem, since there
          >> are many "module a" and module b does not know beforehand
          >> which module had imported it.[/color][/color]

          DB> Ok, I understand now what you are trying to
          DB> achieve, but there isn't any
          DB> concept relating a module back to the first module which tried to import
          DB> it. Instead you'll have to specify the relationship yourself.

          DB> How about this:
          [color=blue][color=green]
          >> #Module c[/color][/color]
          DB> import sys
          DB> food_no = sys.argv[1]
          DB> m = __import__(food _no)
          DB> goodie = b.Salty(m)
          [color=blue][color=green]
          >> #Module b[/color][/color]
          DB> ...
          DB> def Salty(module):
          DB> class Food(SaltyMixIn ,module.Main): pass
          DB> return Food()
          DB> ...

          DB> In fact, it looks like the importing isn't really
          DB> something module c should
          DB> be concerned about. I haven't tested the following code (so it will have
          DB> bugs), but it should give you some ideas. It remembers classes it has
          DB> created so as not to duplicate them, and it also gives each class a
          DB> sensible name.
          [color=blue][color=green]
          >> #Module c[/color][/color]
          DB> import sys
          DB> food_no = sys.argv[1]
          DB> goodie = b.Salty(food_no )
          [color=blue][color=green]
          >> #Module b[/color][/color]
          DB> ...
          DB> import new
          DB> Classes = {}

          DB> def makeFood(classn ame, food, mixin):
          DB> m = __import__(food )
          DB> main = m.Main
          DB> if (mixin, main) in Classes:
          DB> return Classes[mixin, main]()

          DB> newclass = new.classobj(cl assname + '_' + food, (mixin, main), {})
          DB> Classes[mixin, main] = newclass
          DB> return newclass


          DB> def Salty(food):
          DB> return makeFood('Salty ', food, SaltyMixIn)
          DB> ...


          Comment

          • dody suria wijaya

            #6
            Re[5]: Get importer module from imported module

            dsw> New problem though. On line:
            dsw> newclass = new.classobj(cl assname + '_' + food, (mixin, main), {})
            dsw> received "TypeError: metaclass conflict: the metaclass of a
            dsw> derived class must be a (non-strict) subclass of the
            dsw> metaclasses of all its bases".

            Oops, goofed up on me. The above "main" had mistakenly
            pointed to the module. main.Main did the trick.

            -- dsw

            Comment

            Working...