3

In my problem I have a python code that is being started by a user, like:

# file main.py
import sys
import mymodule
config = sys.argv[1]

which imports another module containing functions, classes etc. like

# module.py
def check_config():
 # do something with the content of 'config'
class Module(object):
 # does something with the content of 'config'

How can I access the value of 'config' from within module.py? Should I use a 'global' variable here? Or is there a more sophisticated, pythonic way to solve this problem?

Also, I do not want to define an argument 'config' to each function and class I use in other modules...

Further remark: main.py imports other modules, not the other way around...

asked Aug 19, 2015 at 13:08

4 Answers 4

3

Instead of trying to wrangle global into performing this you should pass config as a parameter.

file main.py

import sys
import mymodule
config = sys.argv[1]
checked = mymodule.check_config(config)
mod = mymodule.Module(config)

module.py

def check_config(config):
 # do something with the content of 'config'
class Module(object):
 # does something with the content of 'config'
 def __init__(self, config):
 # initialise with config

Always avoid usingglobal when you can. If you need to modify config just have a module function return it.

config = change_config(config)

module.py

def change_config(config):
 ...
 return config

However, an alternative method is to define a value within module.py which will store this information that holds nothing by default. Then as soon as file main.py has imported module.py and the config data is ready, you could assign the data to module.py's config name. Like this:

file main.py

import sys
import mymodule
config = sys.argv[1]
mymodule.config = config
mymodule.test_config()
mymodule.check_config()
mymodule.Module()

module.py

config = None
def test_config():
 print config 
 # this will refer to the value supplied from file main.py

Note however, that the values in the module and main file will not be joined. If you reassign config in file main.py for any reason you have to pass that value to the module again. However if you pass a mutable value like a dict or list then you can modify it in file main.py and the values will be shared.

answered Aug 19, 2015 at 13:18

5 Comments

Bus as I mentioned, I might have dozens of classes and hundreds of functions. Your approach does not seem to be very 'pythonic'.
@Alex Passing a parameter is a clean way to have a function get that parameter. Using global would be unclear due to the fact that it's less explicit. Being explicit is Pythonic.
What do you think about the approach described here: effbot.org/pyfaq/…
That will work to an extent but importing is tricky, I think it's easier for us to talk about it on chat because I might be misunderstanding how you intend to use it.
@Alex Writing "Pythonic" code isn't really about typing less -- it's about being explicit and clear. If each of your functions requires config, the clearest thing to do is to take a configuration as an input argument. You might consider wrapping the config into a class and making all of those functions which require it methods of the class, but it probably isn't necessary.
2

I don't recommend using a global variable, but here's the design you should use if you do. config needs to be defined in mymodule; after you import the module, you can set the value of mymodule.config the way you are currently setting config.

# file main.py
import sys
import mymodule
mymodule.config = sys.argv[1]
# module.py
# The exact value doesn't matter, as long as we create the name.
# None is good as it conveys the lack of a value; it's part of your
# module's contract, presumably, that a proper value must be assigned
# before you can use the rest of the module.
config = None
def check_config():
 # do something with the content of 'config'
class Module(object):
 # does something with the content of 'config'
answered Aug 19, 2015 at 13:36

2 Comments

I guess this is a similar approach as given here: effbot.org/pyfaq/… ?
Yeah, it's not a hard pattern to recreate. Essentially, the module is being treated as a class that is instantiated exactly once. The module globals are the instance variables, and any module functions are the methods.
1

A global variable is almost never the answer. Just allow the functions and classes in your "library" (module.py or mymodule.py, you seem to use both) to accept arguments. So:

mymodule.py

def check_config(configuration):
 pass
class Module(object):
 def __init__(self, configuration):
 self.config = configuration
class ConfigError(Exception):
 pass

Then when you want to use them in your "application" code:

main.py

import sys
import mymodule
config = sys.argv[1]
if mymodule.check_config(config):
 myobject = mymodule.Module(config)
else:
 raise mymodule.ConfigError('Unrecognized configuration format.')
answered Aug 19, 2015 at 13:19

2 Comments

Same comment as below: This might work, but then Module is calling different functions and classes, which in turn call other functions and classes. And for EACH of them I have to define the same argument. Looks not nice to me...
Um, code reuse is kind of a thing, though. Not really following your logic. Another way would be to put all of your configuration code into a config.py file, say, and then import config in all of your library files, but you mentioned that you don't want to import in your libraries. You're overly constraining your acceptable solution set.
0

Could you describe that you app should to do? Because now it's not clear, why you want it. Maybe environment variable could help you?

Btw, you can read config file in one place (module), and import all stuff you need from it.

config.py

 import os
 if os.environ['sys'] == 'load_1':
 import load_1 as load
 i = 12
 else:
 import load_2 as load
 i = 13

main.py

 import config
 config.load("some_data")
 print config.i
answered Aug 19, 2015 at 13:30

3 Comments

However, the variable used in the modules and functions can be different between different instances of the same python code. I start e.g. 5 instances to run parallel, but with different 'config' or whatever. Therefore your approach will not solve my problem.
This is baffling! All the more reason to accept the notion of explicitly passing into your objects the configuration each time, accepting my solution or @SuperBiasedMan's.
@Alex, you just should to run it with different config. You can pass with config like environment variable to config module, parse this config and use it in every module you want.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.