编辑:我已经添加了一些关于我为什么要这样做的信息。
以下示例代码纯粹是出于示例目的。最后,我需要让我的代码遍历一个目录结构,当它找到一个python文件时,导入该文件以从中获取数据和可能的函数定义。然后在确定如何处理目录中的其余文件(HTML模板等)时使用它。
因为这个想法是为了使目录结构更适合于保存HTML模板和图像,而python文件实际上更像是一个数据容器(虽然每一次都会有一些功能方面的逻辑),我不想在所有地方都有__init__.py
文件以确保python模块是包的一部分,我觉得搞乱sys.path是错误的解决方案(可能有“meta .py“多个目录中的文件。”
所以,我觉得加载一个python文件的源代码是最好的解决方案。这个问题就是我在下面展示的内容。
想象一下,我有代码执行以下操作:
main.py:
import imp
a = imp.load_source('blah', 'a.py')
print dir(a)
b = imp.load_source('blah', 'b.py')
print dir(b)
a.py:
a = 'a'
b.py:
b = 'b'
运行main.py的结果是:
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a']
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a', 'b']
我希望发生的是第二次调用load_source会创建一个 new 模块并返回它,但看起来它实际上会覆盖现有模块。
目前,我的解决方案是将load_source函数中的'blah'字符串更改为这些模块不会共享的名称(例如文件名),但我想知道是否有更好的方法。< / p>
答案 0 :(得分:6)
Mark,据我所知,如果imp.load_source()
可以导入一个名为“blah”的模块覆盖以前的导入。好吧,你不能通过imp.load_source()
来做到这一点,原因如下:
看一下Python的import.c源代码的一部分:
PyObject *
PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname)
{
PyObject *modules = PyImport_GetModuleDict();
PyObject *m, *d, *v;
m = PyImport_AddModule(name);
if (m == NULL)
return NULL;
/* If the module is being reloaded, we get the old module back
and re-use its dict to exec the new code. */
d = PyModule_GetDict(m);
if (PyDict_GetItemString(d, "__builtins__") == NULL) {
if (PyDict_SetItemString(d, "__builtins__",
PyEval_GetBuiltins()) != 0)
goto error;
}
...
...
您是否注意到有关重新加载模块的评论?因此,一种清晰且非hackish 的方式来做你要求的,就是在导入b.py
时使用另一个名称而不是“blah”。
答案 1 :(得分:1)
不要对不同的模块使用相同的名称。你可以用例如os.path.splitext
获取文件名并使用它,或者只是组成一个名称。
更具体地说,load_source
的第一个参数是模块的名称,如os
或sys
。您告诉imp
导入它假定的相同模块,但是来自不同的文件。它有点奇怪,它不会从头重新导入它,但我想这是一个重新加载优化?请注意,sys.modules
将填充新模块为“blah”,而不是“a”。
您确定要使用Python文件吗?在不了解你的模板引擎的情况下,我真的无法说出任何内容,但如果你只是如此,它可能会更简单。用于设置的目录层次结构中的csv或ini样式文件。