导入模块并在导入时更改模块行为

时间:2011-04-27 16:00:24

标签: python

我想导入一个模块,但导入的行为可能会有所不同,具体取决于我想要施加的某些外部条件。有哪些策略可以实现这一结果?

例子。我想要一个模块foo.py.如果我import foo我得到一个“你好”或“再见”的印刷品,取决于一些独立于模块的外部条件,而是取决于外部因素。一个简单的变量可能是一个全局变量,但我不认为python范围规则允许我从模块foo外部获取全局变量。

示例:

fop.py

import __main__
try:
    __main__.bar
    present = True
except:
    present = False

if present:
    print "present"
else:
    print "not present"

现在,当我导入模块时,我可以获得不同的结果

Python 2.7.1 (r271:86832, Feb 27 2011, 20:04:04) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import foo
not present
>>> 

Python 2.7.1 (r271:86832, Feb 27 2011, 20:04:04) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> bar = 5
>>> import foo
present

我知道这很奇怪,但我有一个非常非常好的理由去做。

3 个答案:

答案 0 :(得分:0)

您实际上可以从模块内部访问主脚本的全局变量。

在主脚本中:

a = 42
import foo

foo.py

import __main__
print __main__.a

请注意,我只说这是可能的:)

答案 1 :(得分:0)

传递有关环境的数据的标准方法是(自然地)使用环境变量:

>>> import os
>>> os.environ['PY_BAR'] = '1'
>>> import foo
"present"

另一种可能的模式是实现自定义 import 例程/钩子,以便在导入foo时,可以在加载模块之后但在之前静默执行下面提到的初始化例程控制权归还。


扩展Sven的模式,您可以使foo模块的初始化显式化,以便外部环境可以影响它。这创建了一个定义明确的文档化界面,用于在使用状态之前将状态注入foo模块:

定义 foo.py 模块:

# define all your classes and functions, then leave global stubs which will 
# be filled in by the module initialization function init(), which _must_ be
# called before the module is used.

_DATA = {}

def use_data():
    # use '_DATA' to do something useful
    ...

def init(state):
    # use 'state' to populate '_DATA'
    ...

定义脚本:

# main configures the state, passing it explicitly to foo
state = {'variable': 42}
import foo
foo.init(state)
foo.use_data()

答案 2 :(得分:0)

你可以使用virtual module这样你就可以在某个地方定义你的模块,把你想要的东西放在里面,每次导入它都会得到这个虚拟模块而不是原始模块。当外部条件发生变化时,您只需重做整个事物并将其他东西放入模块中。

如果您有不同行为的不同文件,您还可以在__init__.py中更改包的搜索路径,如果条件发生变化,您只需将其从sys.modules中删除,以便实际重新加载在下一次导入。