3

My question is simple: I need to pass a string (a path and a file name) only once to a module, for the functions in that module to use. In other words, the functions need a path (and file name) for them to work, and it's not practical to pass that string each time I call a function.

Is there a way I could actually pass a string once (maybe change it later during script) and keep it saved somehow in the module for later use?

Wfarah
  • 90
  • 8
  • You could just have some kind of "init_module()" function that would set up the shared variable within the module – MightyPork Feb 17 '15 at 20:53

3 Answers3

4

You can simply set a global in the module:

variable_to_use = None

def funcA():
    if variable_to_use is None:
        raise ValueError('You need to set module.variable_to_use before using this function')
    do_something_with(variable_to_use)

The variable_to_use is global to all code in the module. Other code can then do:

import module_name

module_name.variable_to_use = 'some value to be used'

Don't be tempted to use from module_name import variable_to_use however, as that'll create a local reference instead, which then is rebound, leaving the module global unchanged.

You could encapsulate setting that global in a function:

def set_variable_to_use(value):
    global variable_to_use
    variable_to_use = value

and use that function instead of setting the module global directly.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • This is exactly what I did! I used a global path string and passed it as an argument to my functions. – Malik Brahimi Feb 17 '15 at 20:55
  • 1
    @MalikBrahimi: no, you didn't. You set function defaults. *That's not the same thing*. See ["Least Astonishment" in Python: The Mutable Default Argument](http://stackoverflow.com/q/1132941) – Martijn Pieters Feb 17 '15 at 20:56
  • @MalikBrahimi: test your code and you'll see that *it doesn't work like that*. The `arg` default value is set **once**, when the function is defined, e.g. when the module is imported. You cannot then change `path` and expect those defaults to follow suit, as *they won't be set again*. – Martijn Pieters Feb 17 '15 at 20:56
  • Thank you, this is exactly what I needed. I actually didn't know that a variable will be a global variable inside the module. – Wfarah Feb 17 '15 at 21:11
2

One option is to add the functions to a class, and use object instances to hold different re-usable values.

class Foo():
    def __init__(self, fpath, fname):
        self.fpath = fpath
        self.fname = fname

    def funcA(self):
        print "do something with the path: {}".format(self.fpath)

    def funcB(self):
        print "do something with the filename: {}".format(self.fname)

if __name__ == '__main__':
    my_object = Foo("/some/path/", "some_filename")
    my_object.funcA()
    my_object.funcB()
aganders3
  • 5,838
  • 26
  • 30
1

You could add a setup function to your module, e.g.

import functools

_path = None

def setup(path):
    global _path
    _path = path

def setup_required(func):
    @functools.wraps(func)
    def wrapped(*args, **kwargs):
        global _path
        if _path is None:
            raise RuntimeError('setup required')
        return func(*args, **kwargs)
    return wrapped

@setup_required
def foo(...):
    with open(_path) as f:
        ....

@setup_required
def bar(...):
    ...

It would be better to wrap the functions that depend on the path in class though, and inject the configured object as a dependency into the code that uses the api you want to expose from the module.

emulbreh
  • 3,421
  • 23
  • 27