在Python中创建匿名模块

在Python中创建匿名模块,python,Python,编辑:我已经添加了一些关于我为什么希望这样做的更多信息。 下面的示例代码仅用于示例目的。最后,我需要让我的代码遍历一个目录结构,当它找到一个python文件时,导入该文件以从中获取数据和可能的函数定义。然后,在确定如何处理目录中的剩余文件(HTML模板等)时,将使用该选项 因为这样做的目的是使目录结构更适合保存HTML模板和图像,而python文件实际上更像是一个数据容器(尽管每隔一段时间就会有函数方面的逻辑),我不想到处都有\uuuu init\uuuu.py文件来确保python模块是包的一

编辑:我已经添加了一些关于我为什么希望这样做的更多信息。

下面的示例代码仅用于示例目的。最后,我需要让我的代码遍历一个目录结构,当它找到一个python文件时,导入该文件以从中获取数据和可能的函数定义。然后,在确定如何处理目录中的剩余文件(HTML模板等)时,将使用该选项

因为这样做的目的是使目录结构更适合保存HTML模板和图像,而python文件实际上更像是一个数据容器(尽管每隔一段时间就会有函数方面的逻辑),我不想到处都有
\uuuu init\uuuu.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:

b、 py:

运行main.py的结果如下:

['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a']
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a', 'b']
我希望发生的是,第二次调用load_source会创建一个新模块并返回它,但看起来它实际上会覆盖现有模块


目前,我的解决方案是将load_源函数中的“blah”字符串更改为这些模块都不会共享的名称(例如它们的文件名),但我想知道是否有更好的方法。

不同的模块不要使用相同的名称。您可以使用例如os.path.splitext来获取文件名并使用该文件名,也可以只编一个名称

更具体地说,
load\u source
的第一个参数是模块的名称,如
os
sys
。您正在告诉
imp
导入它假定为同一模块但来自不同文件的内容。这有点奇怪,它没有从头重新导入,但我猜这是一个重新加载的优化?请注意,
sys.modules
将使用新模块填充为“blah”,而不是“a”



确实要Python文件吗?如果不了解更多关于模板引擎的信息,我真的不能说什么,但是如果在目录层次结构中有csv或ini样式的文件进行设置,可能会更简单。

标记,据我所知,您想知道,
imp.load_source()
是否可以导入一个名为“blah”的模块来覆盖以前的导入。嗯,您不能通过
imp.load\u 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;
   }
   ...
   ...

你注意到关于重新加载模块的评论了吗?因此,一个明确且非黑客的方法就是在导入
b.py
时使用另一个名称,而不是“废话”

通过给不同的模块赋予相同的名称,您试图实现什么?为什么不使用文件名并完成它呢?(就此而言,为什么不导入一个?)@katrielex如果
a.py
存储在一个变量中,因为它是来自用户的参数或来自其他模块的变量,该怎么办?我已经修改了这个问题,以包含更多关于为什么要使用它的信息。由于python文件所在的目录结构,它们将不在sys.path中,因此直接导入将不起作用。如果
a
位于文件系统上的任意路径,该怎么办?虽然这不是我希望的答案,但可能是我得到的最佳答案。另一个想法是删除“旧”属性,或者卸载模块。删除属性可能问题更大,并且当前无法卸载()
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a']
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'a', 'b']
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;
   }
   ...
   ...