在加载模块之前填充模块中的命名空间

时间:2010-12-23 22:18:08

标签: python namespaces import

我在Python中设计了一个配置机制,其中某些对象可以通过特殊方式操作来定义域中的问题。

用户以“config-file”方式使用此对象来指定问题。例如:

# run configuration
CASES = [
 ('Case 1', Item('item1') + Item('item2') + Item('item3')),
 ('Case 2', Item('item1') + Item('item4')),
]

DATA = {
 'Case 1' = {'Piece 1': 'path 1'},
 'Case 2' = {'Piece 1': 'path 2'},
}

Item对象当然是在特定模块中定义的。为了使用它们,您必须发出import声明:from models import Item(当然,我的实际导入更复杂,而不是单个导入)。

我希望用户只需编写显示的配置,而无需导入任何内容(用户很容易忘记这一点)。

我想把文件作为文本读取,并在顶部创建一个包含所有相应导入的辅助文本文件,将其写入文件,然后导入该文件,但这看起来很笨拙。

有什么建议吗?

编辑:

我的系统的工作流程有点类似于Django,因为用户在python文件中定义“设置”,并运行一个脚本,该脚本导入该设置文件并使用它执行操作。这就是我想要这个功能的地方,告诉Python“给定这个命名空间(其中Item特别意味着什么),用户将提供一个脚本 - 执行它并将结果交给我,这样我就可以产生不同的运行”。

2 个答案:

答案 0 :(得分:1)

来自eval帮助:

>>> help(eval)
Help on built-in function eval in module __builtin__:

eval(...)
    eval(source[, globals[, locals]]) -> value

    Evaluate the source in the context of globals and locals.
    The source may be a string representing a Python expression
    or a code object as returned by compile().
    The globals must be a dictionary and locals can be any mapping,
    defaulting to the current globals and locals.
    If only globals is given, locals defaults to it.

也就是说,您可以传入任意字典作为eval调用的命名空间。

with open(source) as f:
    eval(f.read, globals(), {'Item': Item}) 

为什么你决定用户需要用纯Python编写配置文件?您可以使用许多简单的人类可写语言。例如,查看ConfigParser,它会读取Windows使用的基本配置文件。

[cases]
case 1: item1 + item2 + item3
case 2: item1 + item4

[data]
case 1: piece1 - path1
case 2: piece1 - path2

答案 1 :(得分:0)

1)我想到的第一件事就是向用户提供配置文件的生成;怎么会这样 ?

您可以在启动应用程序的脚本中添加参数:

$ python application_run.py --generate_settings 

这将生成一个配置文件,其中包含不同导入的骨架,用户不应每次都添加,例如:

import sys
from models import Item

# Complete the information here please !!!
CASES = []
DATA = {}

2)第二种方式是使用execfile(),你可以为此创建一个将读取settings.py的脚本:

root_settings.py

# All import defined Here.
from Model import Item
...

execfile('settings.py')

现在要读取设置文件信息,只需导入root_settings,就像settings.py中定义的所有变量现在都在root_settings.py名称空间中一样。