30

是否可以在 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 中是否可以将参数传递给模块。

4

6 回答 6

10

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

我认为您正在关注 PyMC2 的一些介绍性示例,这些示例使用了一种模式,其中模块将所有节点代码包装在贝叶斯模型中。这种方法非常适合入门,但正如您所发现的,当您想要运行具有一系列变化的模型时,它可能会受到限制。

幸运的是,PyMC2 可以从列表或字典以及模块中创建 MCMC 对象。在这种情况下,我推荐的正是@oleg-s 在评论中建议的:使用函数。您可以结束函数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))
于 2014-06-05T13:05:26.490 回答
7

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

主文件

"""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)

模块.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...
#
于 2016-07-23T11:36:43.510 回答
6

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

# a.py
parameter = None

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

# c.py
import a
# use a.parameter

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

于 2014-06-05T07:54:14.853 回答
6

我发现定义全局变量并允许它们由 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')

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

于 2018-07-06T19:55:45.373 回答
3

模块范围的全局变量对于大多数用途来说确实足够了,但是如果

  • 该参数需要在模块初始化期间进行评估,或者
  • 您需要具有不同参数的模块的多个版本

在最新版本的 python 中,可以分两步加载,首先是规范,然后是 exec。在中间,您可以设置额外的变量。

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)

在模块中,您可以检查dir()或类似的,以查看变量是否已定义。

于 2020-10-08T13:10:42.387 回答
-1

没有这种方法可以将参数传递给模块,但是您可以稍微修改代码并将模块中的参数作为全局参数导入。

于 2020-10-13T09:30:57.470 回答