Global package variable, is it possible?

C

Chris Allen

Hello fellow pythoneers. I'm stumped on something, and I was hoping
maybe someone in here would have an elegant solution to my problem.
This is the first time I've played around with packages, so I'm
probably misunderstanding something here...

Here's what I'd like to do in my package. I want my package to use a
configuration file, and what I'd like is for the config file to appear
magically in each module so I can just grab values from it without
having to load and parse the config file in each package module. Not
quite understanding how the __init__.py file works, I expected it to
be as easy as just setting up the ConfigParser object and then I
figured (since a package is a module) that it would now be global to
my package and I could access it in my modules, but I was wrong... I
don't want to have to pass it in to each module upon init, or anything
lame like that. A main reason for this is that I'd like to be able to
reload the config file dynamically and have all my modules
automatically receive the new config. There must be a way to do this,
but seeing how __init__.py's namespace is not available within the
package modules, I don't see a simple and elegant way to do this.
Does anybody have any suggestions? Thanks!
 
F

Fabio Z Tessitore

Heve you tried to do something like:

# module configure.py
value1 = 10
value2 = 20
....


# other module
from configure import *

# now I'm able to use value1 value2 etc.
var = value1 * value2

bye
 
C

Carsten Haese

Heve you tried to do something like:

# module configure.py
value1 = 10
value2 = 20
...


# other module
from configure import *

# now I'm able to use value1 value2 etc.
var = value1 * value2

Right idea, wrong execution. Note that the OP said "I'd like to be able
to reload the config file dynamically and have all my modules
automatically receive the new config."

"from configure import *" will import the settings into the current
namespace, and subsequent changes in the original namespace will, in
general, not have any effect in the current namespace.

This should do the trick:

# module configure.py
value1 = 10
value2 = 20
....

# other module
import configure

var = configure.value1 * configure.value2

HTH,
 
C

Chris Allen

Heve you tried to do something like:

# module configure.py
value1 = 10
value2 = 20
...

# other module
from configure import *

# now I'm able to use value1 value2 etc.
var = value1 * value2

bye


Thanks for the response Fabio. I thought about this, but I don't
think this will work well in my situation either. Take a look at the
following:

__init__py:
#######################
_default_cfgfile = 'config.conf'
from configure import *
cfg = loadcfg(_default_cfgfile)

import pkg_module1
import pkg_module2
# EOF


configure.py:
########################
from ConfigParser import SafeConfigParser

def loadcfg(filename):
file = open(filename)
cfg = SafeConfigParser()
cfg.readfp(file)
return cfg
# EOF

pkg_module1:
########################
_default_cfgfile = 'config.conf'
from configure import *
cfg = loadcfg(_default_cfgfile)
# EOF


One problem I see with this approach is that we must define the
configuration file in every module. Alternatively a better approach
would be to only define the configuration file within configure.py,
however this also seems less than ideal. I don't like it because I
believe something as important as the location of the package
configuration file, used by all modules, should defined in __init__
not tucked away in one of it's modules.

Another problem is that after the package is loaded and we want to
load in a new config file, what will happen? With this approach we'll
have to reload every module the package uses for them to read the new
config. And even then, how do we tell each module what the new config
file is? If I did define the configuration file in configure.py then
I suppose what I could do is set a cfgfile variable in configure.py to
the new file location and reload all the modules. If there is no
global package variables, then maybe this isn't so bad...

Hmm. So maybe something like this makes sense:

__init__py:
#######################
_default_cfg_file = 'config.conf'

import configure
def loadcfg(filename):
configure.cfgfile = filename
try:
reload(pkg_module1)
reload(pkg_module2)
except NameError:
pass
cfg = loadcfg(_default_cfg_file)

import pkg_module1
import pkg_module2
# EOF

confgure.py:
#######################
cfgfile = None
def loadcfg()
global cfgfile
if not cfgfile:
return None
file = open(cfgfile)
cfg = SafeConfigParser()
cfg.readfp(file)
return cfg
# EOF

pkg_module1:
#######################
import configure
cfg = configure.loadcfg()
# EOF

It's a little bit convoluted, but I think it solves most of my
gripes. Anybody have a better idea of how to do this? Thanks again
Fabio.
 
C

Chris Allen

Hmm. So maybe something like this makes sense:
__init__py:
#######################
_default_cfg_file = 'config.conf'

import configure
def loadcfg(filename):
configure.cfgfile = filename
try:
reload(pkg_module1)
reload(pkg_module2)
except NameError:
pass
cfg = loadcfg(_default_cfg_file)

import pkg_module1
import pkg_module2
# EOF

confgure.py:
#######################
cfgfile = None
def loadcfg()
global cfgfile
if not cfgfile:
return None
file = open(cfgfile)
cfg = SafeConfigParser()
cfg.readfp(file)
return cfg
# EOF

pkg_module1:
#######################
import configure
cfg = configure.loadcfg()
# EOF

It's a little bit convoluted, but I think it solves most of my
gripes. Anybody have a better idea of how to do this? Thanks again
Fabio.

Ugh... I wasn't thinking... Of course this won't work either for the
same reasons above. changing configure.cfgfile from __init__.py will
have no effect on the separate configure instances loaded in other
modules. I still don't understand why python's __init__.py namespace
isn't global to all modules in the package. Is this a feature, to
prevent sloppy code? I think there are certain instances when it
would make sense.
 
C

Chris Allen

Right idea, wrong execution. Note that the OP said "I'd like to be able
to reload the config file dynamically and have all my modules
automatically receive the new config."

"from configure import *" will import the settings into the current
namespace, and subsequent changes in the original namespace will, in
general, not have any effect in the current namespace.

This should do the trick:

# module configure.py
value1 = 10
value2 = 20
...

# other module
import configure

var = configure.value1 * configure.value2

HTH,

It does help thanks. Okay now after reading your post I really need
to do some experimenting. I was under the impression when I wrote my
last post that changing an attribute in one modules instance in
__init__.py would not effect other modules. Sorry, I'm relatively new
to python, and things like this are still sometimes "gotchas!" for me.
 
F

Fabio Z Tessitore

Il Fri, 03 Aug 2007 14:16:59 -0400, Carsten Haese ha scritto:
Right idea, wrong execution. Note that the OP said "I'd like to be able
to reload the config file dynamically and have all my modules
automatically receive the new config."

You are obviously right ... I haven't read all the post, sorry!

Only for knowing more about modules: is there a way to dinamically reload
an already imported module?

bye
Fabio
 
C

Chris Allen

Only for knowing more about modules: is there a way to dinamically reload
an already imported module?

bye
Fabio

Yeah you can reload modules with the reload builtin function.
 
B

Bruno Desthuilliers

Chris Allen a écrit :
Hello fellow pythoneers. I'm stumped on something, and I was hoping
maybe someone in here would have an elegant solution to my problem.
This is the first time I've played around with packages, so I'm
probably misunderstanding something here...

Here's what I'd like to do in my package. I want my package to use a
configuration file, and what I'd like is for the config file to appear
magically in each module so I can just grab values from it without
having to load and parse the config file in each package module. Not
quite understanding how the __init__.py file works, I expected it to
be as easy as just setting up the ConfigParser object and then I
figured (since a package is a module) that it would now be global to
my package and I could access it in my modules, but I was wrong... I
don't want to have to pass it in to each module upon init, or anything
lame like that. A main reason for this is that I'd like to be able to
reload the config file dynamically and have all my modules
automatically receive the new config. There must be a way to do this,
but seeing how __init__.py's namespace is not available within the
package modules, I don't see a simple and elegant way to do this.
Does anybody have any suggestions? Thanks!

Hi Chris...
I've read all the thread, and it seems that your problem is mostly to
share a single dynamic state (the config) between several modules. So I
do wonder: have you considered the use of the Singleton pattern (or one
of it's variants...) ?
 
B

Ben Finney

Bruno Desthuilliers said:
I've read all the thread, and it seems that your problem is mostly
to share a single dynamic state (the config) between several
modules. So I do wonder: have you considered the use of the
Singleton pattern (or one of it's variants...) ?

Python modules are effectively singletons. So the idiomatic way to do
this is to create a module for configuration (perhaps named 'config'),
import that into every other module that needs it, and use its
attributes.
 
C

Chris Allen

Chris Allen a écrit :





Hi Chris...
I've read all the thread, and it seems that your problem is mostly to
share a single dynamic state (the config) between several modules. So I
do wonder: have you considered the use of the Singleton pattern (or one
of it's variants...) ?

Thanks, I don't know anything about python singletons. But I'll look
it up.
 
C

Chris Allen

Bruno Desthuilliers said:
I've read all the thread, and it seems that your problem is mostly
to share a single dynamic state (the config) between several
modules. So I do wonder: have you considered the use of the
Singleton pattern (or one of it's variants...) ?

Python modules are effectively singletons. So the idiomatic way to do
this is to create a module for configuration (perhaps named 'config'),
import that into every other module that needs it, and use its
attributes.

--
\ "[On the Internet,] power and control will shift to those who |
`\ are actually contributing something useful rather than just |
_o__) having lunch." -- Douglas Adams |
Ben Finney

Yes, that's what I ended up doing. Which is creating a configure
module and then importing it into my modules that use it. I did
something very similar to the code I posted above.
 
B

Bruno Desthuilliers

Chris Allen a écrit :
Thanks, I don't know anything about python singletons.

It's a design pattern, so it's not realluy language specific. I thought
about this because some of your wordings in various posts in this thread
clearly called for such a pattern, but Ben is right, it won't probably
buy you more than a plain python module (which are one of the possible
implementations of the Singleton pattern).
 

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

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,276
Latest member
Sawatmakal

Latest Threads

Top