在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】:

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

ma​​in.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中导入带参数的模块的主要内容,如果未能解决你的问题,请参考以下文章

在 ES6 中导入带或不带大括号 [重复]

带默认参数的模块导出

在windows的cmd中进入带空格的Program Files文件夹

在windows的cmd中进入带空格的Program Files文件夹

python 如何调用带参数的shell脚本

如何编写一个带命令行参数的Python文件