By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,682 Members | 1,071 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,682 IT Pros & Developers. It's quick & easy.

Parametrized module import

P: n/a
I have a module whose behaviour needs to be configurable. The module
needs to decide, the first time it is imported, beteween alternative
interfaces it presents.

Currently, I set some environment variables which select the desired
behaviour, and the module inspects those variables to determine the
mode in which it should set itself up. I would prefer a pure Python
solution, rather than one which depends on external state.

Can you recommend any approaches, or warn against the pitfalls of some
approaches?

Jul 18 '05 #1
Share this Question
Share on Google+
17 Replies


P: n/a
Jacek Generowicz <ja**************@cern.ch> wrote:
I have a module whose behaviour needs to be configurable. The module
needs to decide, the first time it is imported, beteween alternative
interfaces it presents.

Currently, I set some environment variables which select the desired
behaviour, and the module inspects those variables to determine the
mode in which it should set itself up. I would prefer a pure Python
solution, rather than one which depends on external state.

Can you recommend any approaches, or warn against the pitfalls of some
approaches?


You could create another module called "config" or "cfg"
which contains some global variables. You import it into
your configurable module as well as into your main program.
Then you can configure the module's behaviour via those
global variables before importing the module.

Something like this:

#--- File config.py: ---
foo_interface_mode = 0 # default

#--- File your_module.py: ---
import config
if config.foo_interface_mode == 0:
... this interface
else:
... that interface

#--- File main_program.py: ---
import config
config.foo_interface_mode = 1
import your_module

Best regards
Oliver

--
Oliver Fromme, Konrad-Celtis-Str. 72, 81369 Munich, Germany

``All that we see or seem is just a dream within a dream.''
(E. A. Poe)
Jul 18 '05 #2

P: n/a
Oliver Fromme <ol**@haluter.fromme.com> writes:
You could create another module called "config" or "cfg"
which contains some global variables. You import it into
your configurable module as well as into your main program.
Then you can configure the module's behaviour via those
global variables before importing the module.


Yes, my initial crappy prototype idea was to add configuration
information to the sys module, but this variation is much neater
.... in fact, after the first 2 minutes of thinking about it, it looks
perfect :-)

However, one thing which keeps bothering me about the whole business,
is the possibilty of importing the module (with your chosen
configuration) after it has already been imported, without you knowing
it, with a different configuration. Ideally there should be some
warning about the fact that the configuration you specified is being
ignored as a result of the module already being imported ... and I
don't see how to achieve this.

Jul 18 '05 #3

P: n/a
Heather Coppersmith <me@privacy.net> wrote:
Jacek Generowicz <ja**************@cern.ch> wrote:
Oliver Fromme <ol**@haluter.fromme.com> writes:
You could create another module called "config" or "cfg" which
contains some global variables. You import it into your
configurable module as well as into your main program. Then
you can configure the module's behaviour via those global
variables before importing the module.


Yes, my initial crappy prototype idea was to add configuration
information to the sys module, but this variation is much neater
... in fact, after the first 2 minutes of thinking about it, it
looks perfect :-)

However, one thing which keeps bothering me about the whole
business, is the possibilty of importing the module (with your
chosen configuration) after it has already been imported,
without you knowing it, with a different configuration. Ideally
there should be some warning about the fact that the
configuration you specified is being ignored as a result of the
module already being imported ... and I don't see how to achieve
this.


Upon import, a module's "top level" code is executed, so try a
variation on this theme at the top level of your module:


It's only executed when the module is imported for the
_first_ time, so that wouldn't work.

However, the problem can be solved by not modifying a
global variable in the "config" module directly, but by
using a function which allows only one call.

#--- File config.py: ---
foo_interface_mode = None
def set_foo_interface_mode (mode):
if foo_interface_mode is None:
foo_interface_mode = mode
else:
raise "foo_interface_mode may only be set once"

#--- File your_module.py: ---
import config
if config.foo_interface_mode is None:
raise "foo_interface_mode has not been set"
elif config.foo_interface_mode == 0:
... this interface
else:
... that interface

#--- File main_program.py: ---
import config
config.set_foo_interface_mode (1)
import your_module

Of course, you could use assert instead of raise, or just
print a warning and go on. Whatever you prefer.

Best regards
Oliver

--
Oliver Fromme, Konrad-Celtis-Str. 72, 81369 Munich, Germany

``All that we see or seem is just a dream within a dream.''
(E. A. Poe)
Jul 18 '05 #4

P: n/a
Heather Coppersmith <me@privacy.net> writes:
Upon import, a module's "top level" code is executed,
Yes, but only on the _first_ import. On subsequent imports the system
notices that the module has already imported, and doesn't execute
anything in the module, it just binds a name to the already imported
module ...
so try a variation on this theme at the top level of your module:

i_am_configured = False

if i_am_configured:
print 'i am already configured'
else:
import my_configuration_module
configure_myself( )
i_am_configured = True


.... so the first branch will _never_ get executed.

My question is exactly about this problem: nothing gets executed on
the second import, so there's nowhere for me to put the "already
configured" message.

Jul 18 '05 #5

P: n/a
Oliver Fromme <ol**@haluter.fromme.com> writes:
However, the problem can be solved by not modifying a
global variable in the "config" module directly, but by
using a function which allows only one call.

#--- File config.py: ---
foo_interface_mode = None
def set_foo_interface_mode (mode):
if foo_interface_mode is None:
foo_interface_mode = mode
else:
raise "foo_interface_mode may only be set once"


But there must be a default configuration, so you can't check for
None. I typically deal with these situations by using functions which
replace themselves when called:

def configure():
print "Configuring ..."
global configure
def configure():
print "Sorry, already configured."

But this doesn't quite solve the problem I'm trying to solve, which is
to warn, at the time the import statement is executed, that the
configuration which is in place is not being respected.

There's nothing wrong with the user changing the mode twenty times
before the first import. I guess the imported module could block
further configuration changes, and the warning can come when you try
to change the configuration _after_ the first import.

Jul 18 '05 #6

P: n/a
On 08 Jul 2004 09:43:31 +0200
Jacek Generowicz <ja**************@cern.ch> threw this fish to the penguins:
I have a module whose behaviour needs to be configurable. The module
needs to decide, the first time it is imported, beteween alternative
interfaces it presents.

Currently, I set some environment variables which select the desired
behaviour, and the module inspects those variables to determine the
mode in which it should set itself up. I would prefer a pure Python
solution, rather than one which depends on external state.

Can you recommend any approaches, or warn against the pitfalls of some
approaches?


You might look at the way pygtk does it. I haven't peeked inside, but the
api is:

import pygtk
pygtk.require('2.0') # or '1.2' or some other version
import gtk # uses state set by require() to load the appropriate version

The pygtk.py file looks quite reusable with hardly any change...

See: http://www.pygtk.org
-- George
--
"Are the gods not just?" "Oh no, child.
What would become of us if they were?" (CSL)
Jul 18 '05 #7

P: n/a
george young <gr*@ll.mit.edu> writes:
You might look at the way pygtk does it. I haven't peeked inside,
Here is the relevant part ...

def require(version):
global _pygtk_required_version

if _pygtk_required_version != None:
assert _pygtk_required_version == version, \
"a different version of gtk was already required"
return

assert not sys.modules.has_key('gtk'), \
"pygtk.require() must be called before importing gtk"

...
but the api is:

import pygtk
pygtk.require('2.0') # or '1.2' or some other version
import gtk # uses state set by require() to load the appropriate version


Yup ... but now I'm being put under pressure to make the API thus:

import foo
foo.config....

which doesn't thrill me at all, for a plethora of implementation
detail related reasons which are not interesting here.

Thanks for the poniter, anyway.
Jul 18 '05 #8

P: n/a
Jacek Generowicz wrote:
I have a module whose behaviour needs to be configurable. The module
needs to decide, the first time it is imported, beteween alternative
interfaces it presents.

Currently, I set some environment variables which select the desired
behaviour, and the module inspects those variables to determine the
mode in which it should set itself up. I would prefer a pure Python
solution, rather than one which depends on external state.

Can you recommend any approaches, or warn against the pitfalls of some
approaches?


Following `explicit is better than implicit` I'd prefer to have a huge
interface class or object that would be instantiated with parameters.
Something like this:

from myModule import myModule

myModule.tweak(<blah>)

....

myModule.doSomething()

Of course, this solution might not fit your needs.

regards,
anton.
Jul 18 '05 #9

P: n/a
anton muhin <an********@rambler.ru> writes:
Of course, this solution might not fit your needs.


In this case, I am afraid that it does not.
Jul 18 '05 #10

P: n/a
On 08 Jul 2004 14:22:25 +0200,
Jacek Generowicz <ja**************@cern.ch> wrote:
Heather Coppersmith <me@privacy.net> writes:
Upon import, a module's "top level" code is executed,
Yes, but only on the _first_ import. On subsequent imports the system
notices that the module has already imported, and doesn't execute
anything in the module, it just binds a name to the already imported
module ... so try a variation on this theme at the top level of your module:

i_am_configured = False

if i_am_configured:
print 'i am already configured'
else:
import my_configuration_module
configure_myself( )
i_am_configured = True

... so the first branch will _never_ get executed. My question is exactly about this problem: nothing gets executed on
the second import, so there's nowhere for me to put the "already
configured" message.


Oops--yes, you are correct. I apologize. My quickie tests were
apparently less than sufficient. [slaps self on wrist, and then
on forehead]

Regards,
Heather

--
Heather Coppersmith
That's not right; that's not even wrong. -- Wolfgang Pauli
Jul 18 '05 #11

P: n/a
On 08 Jul 2004 16:28:21 +0200, Jacek Generowicz
<ja**************@cern.ch> wrote:

Yup ... but now I'm being put under pressure to make the API thus:

import foo
foo.config....

which doesn't thrill me at all, for a plethora of implementation
detail related reasons which are not interesting here.

Thanks for the poniter, anyway.


How ugly is this:

import sys

def __config():
return sys._getframe(2).f_globals.get('__magic_config', None)

def config(name):
name = str(name)
if name not in __mapping:
raise RuntimeException, "unknown flavor " + name
sys._getframe(1).f_globals['__magic_config'] = name

def __default_bar(*a, **kw):
print "I am the default"

def __white_bar(*a, **kw):
print "I am white"

def __black_bar(*a, **kw):
print "I am black"

__mapping = {'bar': {None: __default_bar,
'white': __white_bar,
'black': __black_bar},
}

for i in __mapping:
globals()[i] = lambda *a, **kw: __mapping[i][__config()](*a, **kw)

I'd say about 6 in a fuglyness scale, but it might do what you want.
I'm sure there's an easyer way of putting things into the current
namespace, but this works.

--
John Lenton (jl*****@gmail.com) -- Random fortune:
bash: fortune: command not found
Jul 18 '05 #12

P: n/a
On Thu, 8 Jul 2004 13:25:25 -0300, John Lenton <jl*****@gmail.com> wrote:
raise RuntimeException, "unknown flavor " + name


that should've been RuntimeError, and flavour.

--
John Lenton (jl*****@gmail.com) -- Random fortune:
bash: fortune: command not found
Jul 18 '05 #13

P: n/a
Jacek Generowicz <ja**************@cern.ch> wrote:
But this doesn't quite solve the problem I'm trying to solve, which is
to warn, at the time the import statement is executed, that the
configuration which is in place is not being respected.
I see.
There's nothing wrong with the user changing the mode twenty times
before the first import. I guess the imported module could block
further configuration changes, and the warning can come when you try
to change the configuration _after_ the first import.


In that case, why don't you let the imported module change
the definition of the function in the "config" module?
That's exactly the place after which modifications should
be disallowed, if I understand you correctly.

Third try.

#--- File config.py: ---
foo_interface_mode = 0 # default
def set_foo_interface_mode (mode):
foo_interface_mode = mode

#--- File your_module.py: ---
import config

def config_warn():
print "foo_interface_mode may only be set once!"

config.set_foo_interface_mode = config_warn

if config.foo_interface_mode == 0:
... this interface
else:
... that interface

#--- File main_program.py: ---
import config
config.set_foo_interface_mode (1)
import your_module

Best regards
Oliver

--
Oliver Fromme, Konrad-Celtis-Str. 72, 81369 Munich, Germany

``All that we see or seem is just a dream within a dream.''
(E. A. Poe)
Jul 18 '05 #14

P: n/a
On 08 Jul 2004 16:28:21 +0200, Jacek Generowicz
<ja**************@cern.ch> wrote:

Yup ... but now I'm being put under pressure to make the API thus:

import foo
foo.config....

which doesn't thrill me at all, for a plethora of implementation
detail related reasons which are not interesting here.

Thanks for the poniter, anyway.


How ugly is this:

import sys

def __config():
return sys._getframe(2).f_globals.get('__magic_config', None)

def config(name):
name = str(name)
if name not in __mapping:
raise RuntimeException, "unknown flavor " + name
sys._getframe(1).f_globals['__magic_config'] = name

def __default_bar(*a, **kw):
print "I am the default"

def __white_bar(*a, **kw):
print "I am white"

def __black_bar(*a, **kw):
print "I am black"

__mapping = {'bar': {None: __default_bar,
'white': __white_bar,
'black': __black_bar},
}

for i in __mapping:
globals()[i] = lambda *a, **kw: __mapping[i][__config()](*a, **kw)

I'd say about 6 in a fuglyness scale, but it might do what you want.
I'm sure there's an easyer way of putting things into the current
namespace, but this works.

--
John Lenton (jl*****@gmail.com) -- Random fortune:
bash: fortune: command not found
Jul 18 '05 #15

P: n/a
Oliver Fromme <ol**@haluter.fromme.com> writes:
> I guess the imported module could block further configuration
> changes, and the warning can come when you try to change the
> configuration _after_ the first import.
#--- File config.py: ---
foo_interface_mode = 0 # default
def set_foo_interface_mode (mode):
foo_interface_mode = mode

#--- File your_module.py: ---
import config

def config_warn():
print "foo_interface_mode may only be set once!"

config.set_foo_interface_mode = config_warn


Yup, that's exactly the sort of thing I was suggesting.
Jul 18 '05 #16

P: n/a
Jacek Generowicz wrote:
I have a module whose behaviour needs to be configurable. The module
needs to decide, the first time it is imported, beteween alternative
interfaces it presents.

Currently, I set some environment variables which select the desired
behaviour, and the module inspects those variables to determine the
mode in which it should set itself up. I would prefer a pure Python
solution, rather than one which depends on external state.

Can you recommend any approaches, or warn against the pitfalls of some
approaches?

What I would recommend is class-ifying the code inside the module. Then
you can create a fresh object each time you want a different
configuration, and you don't have to worry about the relationship
between import and configure.
This may make your module more flexible as well

David
Jul 18 '05 #17

P: n/a
On 08 Jul 2004 12:58:51 +0200,
Jacek Generowicz <ja**************@cern.ch> wrote:
Oliver Fromme <ol**@haluter.fromme.com> writes:
You could create another module called "config" or "cfg" which
contains some global variables. You import it into your
configurable module as well as into your main program. Then
you can configure the module's behaviour via those global
variables before importing the module.

Yes, my initial crappy prototype idea was to add configuration
information to the sys module, but this variation is much neater
... in fact, after the first 2 minutes of thinking about it, it
looks perfect :-) However, one thing which keeps bothering me about the whole
business, is the possibilty of importing the module (with your
chosen configuration) after it has already been imported,
without you knowing it, with a different configuration. Ideally
there should be some warning about the fact that the
configuration you specified is being ignored as a result of the
module already being imported ... and I don't see how to achieve
this.


Upon import, a module's "top level" code is executed, so try a
variation on this theme at the top level of your module:

i_am_configured = False

if i_am_configured:
print 'i am already configured'
else:
import my_configuration_module
configure_myself( )
i_am_configured = True

HTH,
Heather

--
Heather Coppersmith
That's not right; that's not even wrong. -- Wolfgang Pauli
Jul 18 '05 #18

This discussion thread is closed

Replies have been disabled for this discussion.