Alex
Alex

Reputation: 44395

How to use a 'global' variable in python?

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...

Upvotes: 3

Views: 785

Answers (4)

SuperBiasedMan
SuperBiasedMan

Reputation: 9969

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.

Upvotes: 3

chepner
chepner

Reputation: 532238

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'

Upvotes: 2

Jimilian
Jimilian

Reputation: 3919

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

Upvotes: 0

Andy Kubiak
Andy Kubiak

Reputation: 169

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.')

Upvotes: 1

Related Questions