How can a module know the module that imported it?

How can a module know the module that imported it?

Post by kj » Fri, 13 Nov 2009 05:16:50



The subject line says it all.

Thanks!

kynn
 
 
 

How can a module know the module that imported it?

Post by aahz » Fri, 13 Nov 2009 06:12:26


You are probably trying to remove a *** with a hammer -- why don't you
tell us what you really want to do and we'll come up with a Pythonic
solution?
--
Aahz ( XXXX@XXXXX.COM ) <*> http://www.yqcomputer.com/

[on old computer technologies and programmers] "Fancy tail fins on a
brand new '59 Cadillac didn't mean throwing out a whole generation of
mechanics who started with model As." --Andrew Dalke

 
 
 

How can a module know the module that imported it?

Post by Ethan Furm » Fri, 13 Nov 2009 06:44:06


Well, I don't know what kj is trying to do, but my project is another
(!) configuration program. (Don't worry, I won't release it... unless
somebody is interested, of course !)

So here's the idea so far:
The configuration data is stored in a python module (call it
settings.py). In order to be able to do things like add settings to it,
save the file after changes are made, etc., settings.py will import the
configuration module, called configure.py.

A sample might look like this:

<settings.py>
import configure

paths = configure.Item()
paths.tables = 'c:\\app\\data'
paths.temp = 'c:\\temp'
</settings.py>

And in the main program I would have:

<some_app.py>
import settings

main_table = dbf.Table('%s\\main' % paths.tables)

# user can modify path locations, and does, so update
# we'll say it changes to \work\temp

settings.paths.temp = user_setting()
settings.configure.save()
</some_app.py>

And of course, at this point settings.py now looks like

<settings.py>
import configure

paths = configure.Item()
paths.tables = 'c:\\app\\data'
paths.temp = 'c:\\work\\temp'
</settings.py>

Now, the tricky part is the line

settings.configure.save()

How will save know which module it's supposed to be re-writing? The
solution that I have for now is

def _get_module():
"get the calling module -- should be the config'ed module"
target = os.path.splitext(inspect.stack()[2][1])[0]
target = __import__(target)
return target

If there's a better way, I'd love to know about it!

Oh, and I'm using 2.5.4, but I suspect kj is using 2.6.

~Ethan~
 
 
 

How can a module know the module that imported it?

Post by kj » Fri, 13 Nov 2009 06:55:58

In <hdf9bq$59s$ XXXX@XXXXX.COM > XXXX@XXXXX.COM (Aahz) writes:




Worse: I'm trying to write Perl using Python!


Because the problem that gave rise to this question is insignificant.
I would want to know the answer in any case. *Can* it be done in
Python at all?

OK, if you must know:

With Perl one can set a module-global variable before the module
is loaded. This provides a very handy backdoor during testing.
E.g.

# in t/some_test.t script
...
BEGIN { $My::Module::TESTING = 1; }
use My::Module;
...

and in My/Module.pm:

package My::Module;
our $TESTING ||= 0; # set to 0 unless already initialized to !0
...
if ($TESTING) {
# throw testing switches
}


This does not work in Python, because setting my.module.TESTING
variable can happen only after my.module has been imported, but by
this point, the module's top-level code has already been executed,
so setting my.module.TESTING would have no effect. But one way to
get a similar effect would be to have my.module set its TESTING
(or whatever) variable equal to the value of this variable in the
*importing* module.

kynn
 
 
 

How can a module know the module that imported it?

Post by Diez B. Ro » Fri, 13 Nov 2009 07:47:31

> Because the problem that gave rise to this question is insignificant.

No.


I don't understand enough (actually nothing) from perl, but I *am* a
heavily test-driven developer in Python. And never felt that need.

Sure, sometimes one wants to change behavior of a module under test,
e.g. replacing something with a stub or some such.

But where is the problem doing


--- mytest.py ---

import moduletobetested as m

m.SOME_GLOBAL = "whatever"

m.do_something()

---


Diez
 
 
 

How can a module know the module that imported it?

Post by Christian » Fri, 13 Nov 2009 07:50:20


That's terrible style! Code should not react differently if you run it
inside an unit test harness. If you need to change the environment for
tests because you can test all aspects of your runtime environment, use
a mock up system. Please read
http://www.yqcomputer.com/ 't
know the term.

Christian
 
 
 

How can a module know the module that imported it?

Post by Steven D'A » Fri, 13 Nov 2009 08:21:26


Any time somebody justifies a features as "a very handy backdoor", a
billion voices cry out and then are suddenly silenced...

[...]

(1) Then change your design so you're not relying on changing the
behaviour of top-level code. Instead of:

chant_incantation(arg) # effect module.magic, somehow...
import module
do_something_with( module.magic )

(where magic is created by the top-level code)


do this instead:

import module
do_something_with( module.make_magic(arg) )




(2) If you still want a back-door, encapsulate it in another module:


# Contents of module.py

import _secret_backdoor
if _secret_backdoor.manna > 17:
magic = 42
else:
magic = 23


Then in your calling code:

# chant an incantation to change the behaviour of module
import _secret_backdoor
_secret_backdoor.manna = 1003

import module
do_something_with(module.magic)


(3) Abuse __builtins__ by polluting it with your own junk:


# Contents of module.py

try:
my_secret_name12761
except NameError:
magic = 23
else:
magic = 42



Then in your calling code:

# chant an incantation to change the behaviour of module
import __builtins__
__builtins__.my_secret_name12761 = None

import module
do_something_with(module.magic)


But if you do this one, hundreds of Python developers carrying flaming
torches and pitchforks will track you down and do terrible things to your
corpse...


*wink*




--
Steven
 
 
 

How can a module know the module that imported it?

Post by AK Eri » Sat, 14 Nov 2009 02:49:53

so:

# moduleA.py
import moduleB

# moduleB.py
import sys
stuff = sys._getframe(1).f_locals
print stuff

Prints:

{'__builtins__': <module '__builtin__' (built-in)>,
'__file__': 'C:\\Documents and Settings\\<userName>\\My Documents\
\python\\moduleA.py',
'__name__': '__main__',
'__doc__': None}

Looks like you could query stuff['__file__'] to pull what you're
after.
?
 
 
 

How can a module know the module that imported it?

Post by Ethan Furm » Sat, 14 Nov 2009 03:10:53


The leading _ in _getframe indicates a private function to sys (aka
implementation detail); in other words, something that could easily
change between one Python version and the next.

I'm using the inspect module (for the moment, at least), and my question
boils down to: Will it work correctly on all versions of Python in the
2.x range? 3.x range?

~Ethan~
 
 
 

How can a module know the module that imported it?

Post by AK Eri » Sat, 14 Nov 2009 03:35:55


Good point, I totally missed that. Someone had passed that solution
to me at one point and I was so e *** d I kind of looked that over :P