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