在python中导入带有参数的模块

import a module with parameter in python

是否可以在python中传递带有某些参数的导入模块?

我所指的参数是,模块中存在一个未在该模块中初始化的变量,但我仍在该模块中使用该变量。简而言之,我希望行为与函数相似,但与函数不同,我希望在调用代码中公开模块的变量。

A.Py

1
2
3
#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

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

我希望a.py中的所有随机变量都暴露在mcmc中。对于手头的问题,我愿意采用更好的方法,但我也想知道为什么在Python中可以将参数传递给模块


正如@otus已经回答的那样,无法将参数传递给模块。

我认为您正在遵循PYMC2的一些介绍性示例,其中使用的模式是模块将节点的所有代码包装在贝叶斯模型中。这种方法对于开始是很好的,但是,正如您已经发现的,当您想要用一系列的变化来运行您的模型时,可能会受到限制。

幸运的是,pymc2可以从列表或字典以及模块中创建一个mcmc对象。在这种情况下,我推荐的只是@oleg-s在注释中建议的:使用函数。您可以使用return locals()结束函数,以获取模块中所有内容的字典,这是pymc.MCMC构造函数的适当输入。下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
# 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()
1
2
3
4
5
# b.py
import pymc, a

training_pool = [0]
m = pymc.MCMC(a.model(training_pool))

有各种方法可以做到这一点,这里只是一个愚蠢而简单的方法:

Me.Py

1
2
3
4
5
6
7
8
9
10
11
12
"""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)

模块化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
"""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...
#


无法将参数传递给模块。但是,您可以在第三个模块中为此使用全局:

1
2
# a.py
parameter = None
1
2
3
4
# b.py
import a
a.parameter = 4
import c
1
2
3
# c.py
import a
# use a.parameter

当然,只有在没有其他东西导入C时,这才有效,因为模块只导入一次。


我发现有助于定义全局变量,并允许这些变量由init函数来设置。

1
2
3
4
5
6
7
8
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']

然后,所有用户必须记住在使用这些方法之前初始化模块:

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

注意,我不会在我希望公开传播的模块上使用这个。这更适合我个人使用的单个文件模块。