在python中导入带参数的模块
Posted
技术标签:
【中文标题】在python中导入带参数的模块【英文标题】:Import a module with parameter in python 【发布时间】:2014-07-26 02:05:03 【问题描述】:是否可以在 python 中导入带有某些参数的模块?
参数的意思是模块中存在一个未在该模块中初始化的变量,但我仍在该模块中使用该变量。简而言之,我希望行为类似于函数但与函数不同,我希望将模块的变量暴露在调用代码中。
例如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)
我希望a.py
中的所有随机变量都暴露给MCMC
。我愿意为手头的问题提供更好的方法,但我也想知道在 python 中是否可以将参数传递给模块。
【问题讨论】:
你要from a import *
吗?
我想他要的是module-wide globals。
将 a.py 中的代码包装到一个函数中,然后将参数传递给该函数!
@Oleg,我不想那样做,因为在那种情况下,这些变量,如 x,rv 将成为函数的局部变量,MCMC 将无法从中采样
这是一个不寻常的模式,但看起来它是在 pymc 中完成的方式......建议复制他们的一个工作示例,然后对其进行修改以了解正在发生的事情
【参考方案1】:
正如@otus 已经回答的那样,没有办法将参数传递给模块。
我认为您正在关注 PyMC2 的一些介绍性示例,这些示例使用了一种模式,其中模块将所有节点代码包装在贝叶斯模型中。这种方法非常适合入门,但正如您所发现的,当您想要运行具有一系列变化的模型时,它可能会受到限制。
幸运的是,PyMC2 可以从列表或字典以及模块中创建 MCMC 对象。在这种情况下,我推荐的正是 @oleg-s 在 cmets 中建议的:使用函数。您可以使用return locals()
结束函数,以获取模块中所有内容的字典,这是pymc.MCMC
构造函数的合适输入。这是一个例子:
# 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))
【讨论】:
【参考方案2】:有多种方法可以做到这一点,这里只是一种愚蠢而简单的方法:
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...
#
【讨论】:
【参考方案3】:我发现定义全局变量并允许通过 init 函数设置这些变量很有帮助。
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']
那么用户所要做的就是记住在使用这些方法之前初始化模块:
import module
module.init('config.ini')
注意,我不会在我希望公开传播的模块上使用它。这更适合我个人使用的单文件模块。
【讨论】:
【参考方案4】:无法将参数传递给模块。但是,您可以为此在第三个模块中使用全局变量:
# a.py
parameter = None
# b.py
import a
a.parameter = 4
import c
# c.py
import a
# use a.parameter
当然,这只有在没有其他东西导入 c 时才有效,因为模块只会被导入一次。
【讨论】:
【参考方案5】:模块范围的全局变量对于大多数用途来说确实足够了,但是如果
需要在模块初始化期间评估参数,或者 您需要具有不同参数的多个版本的模块在最新版本的 python 中,可以分两步加载,首先是规范,然后是 exec。中间可以设置额外的变量。
import importlib
abstract=importlib.util.find_spec('myModule')
module4=importlib.util.module_from_spec(abstractModule.__spec__)
module2=importlib.util.module_from_spec(abstractModule.__spec__)
module2.parameter="you are version 2"
module4.parameter="you are version 4"
module4.__spec__.loader.exec_module(module4)
module2.__spec__.loader.exec_module(module2)
在模块中你可以检查dir()
或类似的,看看变量是否被定义。
【讨论】:
【参考方案6】:没有这种方法可以将参数传递给模块,但是您可以稍微修改一下代码并将模块中的参数作为全局参数导入。
【讨论】:
欢迎来到 SO!请阅读tour和How do I write a good answer?以上是关于在python中导入带参数的模块的主要内容,如果未能解决你的问题,请参考以下文章
在windows的cmd中进入带空格的Program Files文件夹