Import a module with parameter in python
Asked Answered
A

7

34

Is it possible to import a module with some parameter in python ?

All I mean by parameter is that there exists a variable in the module which is not initialized in that module, still I am using that variable in that module. In short, I want behavior similar to a function but unlike function, I want the variables of module to be exposed in the calling code.

eg a.py:

#lists like data, count, prob_distribution are constructed from training_pool (not initialized in this file)
x = pymc.Uniform('x', lower = 0, upper = 1)
rv = [ Multinomial("rv"+str(i), count[i], prob_distribution[i], value = data[i], observed=True) for i in xrange(0, len(count)) ]

b.py:

import a  #I want some way tr pass value of training_pool
m = pymc.MCMC(a)

I want all random variables in a.py to be exposed to MCMC. I am open to a better approach for my problem at hand, but I would also like to know whether passing arguments to modules is possible in python or not.

Airtoair answered 5/6, 2014 at 7:23 Comment(5)
Are you asking for from a import *?Borlase
I think he's asking for module-wide globals.Albritton
Wrap your code in a.py into a function and pass parameters to that function instead!Taiga
@Oleg, I don't want to do that as in that case, these vaiables like x, rv will become local variables of the function, and MCMC won't be able to sample from themAirtoair
This is an unusual pattern to be using but looks like it is the way things are done in pymc... Suggest copying one of their working examples then modifying that to get an understanding of what's going onEnglert
G
11

As @otus already answered, there is no way to pass parameters to modules.

I think you are following some of the introductory examples for PyMC2, which use a pattern where a module wraps all the code for the nodes in a Bayesian model. This approach is good for getting started, but, as you have found, can be limiting, when you want to run your model with a range of variations.

Fortunately, PyMC2 can create an MCMC object from a list or a dictionary as well as a module. What I recommend in this case is just what @oleg-s suggested in the comments: use a function. You can end the function with return locals() to get a dictionary of everything that would have been in the module, and this is suitable input to the pymc.MCMC constructor. Here is an example:

# a.py
from pymc import *

count = [10, 10] # perhaps good to put this stuff in data.py
prob_distribution = [[.5, .5], [.1, .2, .7]]
data = [[2, 8], [2, 3, 5]]

def model(training_pool):
    x = Uniform('x', lower = 0, upper = 1)
    rv = [ Multinomial("rv"+str(i), count[i], prob_distribution[i], value = data[i], observed=True) for i in training_pool ]

    return locals()

# b.py
import pymc, a

training_pool = [0]
m = pymc.MCMC(a.model(training_pool))
Gainer answered 5/6, 2014 at 13:5 Comment(0)
D
12

there are various approaches to do so, here is just a silly and simple one:

main.py

"""A silly example - main supplies a parameter
"""

import sys,os

print os.path.basename(__file__)+":Push it by: --myModuleParam "+str(123)
sys.argv.append('--myModuleParam')
sys.argv.append(123)
import module


print os.path.basename(__file__)+":Pushed my  param:"+str(module.displayMyParam)

module.py

"""A silly example - module consumes parameter
"""

import sys,os

displayMyParam = 'NotYetInitialized'

for px in sys.argv:
    if px == '--myModuleParam':
        idx = sys.argv.index(px)
        sys.argv.pop(idx) # remove option
        displayMyParam = sys.argv[idx]
        sys.argv.pop(idx) # remove value
        print os.path.basename(__file__)+":Got my param:"+str(displayMyParam)

#
# That's it...
#
Dismiss answered 23/7, 2016 at 11:36 Comment(0)
G
11

As @otus already answered, there is no way to pass parameters to modules.

I think you are following some of the introductory examples for PyMC2, which use a pattern where a module wraps all the code for the nodes in a Bayesian model. This approach is good for getting started, but, as you have found, can be limiting, when you want to run your model with a range of variations.

Fortunately, PyMC2 can create an MCMC object from a list or a dictionary as well as a module. What I recommend in this case is just what @oleg-s suggested in the comments: use a function. You can end the function with return locals() to get a dictionary of everything that would have been in the module, and this is suitable input to the pymc.MCMC constructor. Here is an example:

# a.py
from pymc import *

count = [10, 10] # perhaps good to put this stuff in data.py
prob_distribution = [[.5, .5], [.1, .2, .7]]
data = [[2, 8], [2, 3, 5]]

def model(training_pool):
    x = Uniform('x', lower = 0, upper = 1)
    rv = [ Multinomial("rv"+str(i), count[i], prob_distribution[i], value = data[i], observed=True) for i in training_pool ]

    return locals()

# b.py
import pymc, a

training_pool = [0]
m = pymc.MCMC(a.model(training_pool))
Gainer answered 5/6, 2014 at 13:5 Comment(0)
J
9

There is no way to pass parameters to modules. However, you could use a global in a third module for this:

# a.py
parameter = None

# b.py
import a
a.parameter = 4
import c

# c.py
import a
# use a.parameter

Of course, this only works if nothing else imports c, because modules only get imported once.

Janitress answered 5/6, 2014 at 7:54 Comment(0)
S
7

I found it helpful to define global variables, and allow these to be set by an init function.

def init(config_filename=CONFIG_FILENAME):
    config = configparser.ConfigParser(interpolation=configparser.ExtendedInterpolation())
    config.read(config_filename)

    global YEARS
    YEARS = config['DEFAULT']['YEARS']
    global FEATURES
    FEATURES = config['DEFAULT']['FEATURES']

Then all the user has to do is remember to initialize the module before using these methods:

import module
module.init('config.ini')

Note, I would NOT use this on a module that I expect to spread publicly. This is more for single-file modules for my own personal use.

Subfloor answered 6/7, 2018 at 19:55 Comment(0)
K
4

Module-wide globals should be indeed enough for most uses, but what if

  • the parameter needs to be evaluated during module initialization, or
  • you need multiple versions of the module with different parameters

In recent versions of python, it is possible to load in two steps, first the spec, then exec. In the middle, you can set up extra variables.

import importlib
abstractModuleSpec=importlib.util.find_spec('myModule')
module4=importlib.util.module_from_spec(abstractModuleSpec)
module2=importlib.util.module_from_spec(abstractModuleSpec)
module2.parameter="you are version 2"
module4.parameter="you are version 4"
module4.__spec__.loader.exec_module(module4)
module2.__spec__.loader.exec_module(module2)

In the module you can check dir() or similar, to see if the variable is defined.

Kratzer answered 8/10, 2020 at 13:10 Comment(0)
A
1

I really wonder nobody mentioned environment variables. That's the cleanest way I found:

a.py

import os
param = os.getenv('MY_PACKAGE_PARAM', None)
print(param)

b.py

import os
os.setenv('MY_PACKAGE_PARAM', 'Hello world!')
import a
Acicular answered 11/1, 2023 at 14:0 Comment(0)
U
-1

There is no such way to pass parameters to the module, however you can revamp your code a bit and import the parameters from a module as global parameters.

Unending answered 13/10, 2020 at 9:30 Comment(1)
Welcome to SO! Please read the tour, and How do I write a good answer?Marchand

© 2022 - 2024 — McMap. All rights reserved.