who imported me?

Alex Martelli aleaxit at yahoo.com
Fri Jan 19 04:51:49 EST 2001


<sragsdale at my-deja.com> wrote in message news:947jh5$puv$1 at nnrp1.deja.com...
> (Hopefully) easy question: I'm writing a module that uses values in
> variables from the script that imported it.

A very bad practice, like most all practice relying on global
variables; it will not 'scale' well and is likey to cause you
nothing but trouble.  I suggest a redesign and refactoring.


> How can I tell which script is importing me?

Your module's code is executed the FIRST time some other module
imports it, and, also, when the reload built-in function is used.

All other imports have no effect on your module, *just* on the
namespaces your module is being imported from.

If detecting the FIRST import is what you want (and you can
handle reloads), then a general approach can be something like:

import sys

try: raise 'foo'
except 'foo':
    impname = sys.exc_info()[2].tb_frame.f_back.f_globals['__name__']
    importing_module = sys.modules[impname]

The importing_module variable is now bound to the module object
that is importing you (for the first time, or by reload); the
name of that module is referred to by variable impname.


> Is there some easier way to get the parent module's variable values?

A module does not have a 'parent module' in general: there is not
even a directed acyclic graph of imports, as cycles are possible
(although dependency cycles are never a good idea, of course).

Further, when the module is first imported, variable values in the
importing modules are often not yet defined; the import statement
is generally placed before other variables' definitions.

If you want one module to pass variables to another, I suggest you
do so explicitly: have the 'child' module define an init function,
and the 'parent' module call it with the dictionary of values to
be passed.  This may just mean placing right after the:

import child

a line of:

child.init(globals())

if you want to pass all of the currently-defined names-values
dictionary; but this explicit setup is clearer and more flexible
than any obscure metaprogramming/reflection/introspection trick
you might be playing, such as the one I exemplify above.

If you consider that a module will often be imported by several
places, each wanting to pass it ITS own settings, you may also
realize that a module is not the ideal way to do this -- it may
well be preferable to define a *class* in the module, and use
*instances* of that class from the various 'importers'.  When
you create such an instance, you get to pass whatever you want
as the arguments to the constructor (received as arguments to
the __init__ method of the class you're "calling" for creation).


Alex






More information about the Python-list mailing list