Get importer module from imported module

  • Thread starter dody suria wijaya
  • Start date
D

dody suria wijaya

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
==============
import a
a.How()


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.
 
D

Duncan Booth

dody said:
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
==============



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.

'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.
 
D

dody suria wijaya

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_importing_me.Main): pass
return Food()
def Sweet():
class Food(SugaryMixIn,module_importing_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(SaltyMixIn,Main): pass # new
class Sweet(SaltyMixIn,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> '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.
 
D

Duncan Booth

dody said:
"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.

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:
#Module c
import sys
food_no = sys.argv[1]
m = __import__(food_no)
goodie = b.Salty(m)
#Module b
....
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.
#Module c
import sys
food_no = sys.argv[1]
goodie = b.Salty(food_no)
#Module b
....
import new
Classes = {}

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

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


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

dody suria wijaya

Yup, Got it.

New problem though. On line:

newclass = new.classobj(classname + '_' + 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> 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:
DB> import sys
DB> food_no = sys.argv[1]
DB> m = __import__(food_no)
DB> goodie = b.Salty(m)
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.
DB> import sys
DB> food_no = sys.argv[1]
DB> goodie = b.Salty(food_no)
DB> ...
DB> import new
DB> Classes = {}

DB> def makeFood(classname, 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(classname + '_' + food, (mixin, main), {})
DB> Classes[mixin, main] = newclass
DB> return newclass


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

dody suria wijaya

dsw> New problem though. On line:
dsw> newclass = new.classobj(classname + '_' + 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
 

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

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top