gpt4 book ai didi

python - 通过 imp.load_source 加载具有相同名称的模块导致模块合并

转载 作者:太空狗 更新时间:2023-10-29 20:12:46 25 4
gpt4 key购买 nike

我想知道以下行为是预期的还是错误。我正在使用 CPython2.7

创建文件x.py

def funcA():
print "funcA of x.py"
def funcB():
print "funcB of x.py"

创建文件y.py

def funcB():
print "funcB of y.py"

创建文件test.py

import sys, imp
# load x.py as fff
m = imp.load_source('fff', 'x.py')
print dir(m)
print sys.modules.get('fff')
# load y.py as fff
m = imp.load_source('fff', 'y.py')
print dir(m)
print sys.modules.get('fff')

# import and exec func
import fff
fff.funcA()
fff.funcB()
print dir(fff)

结果

['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'funcA', 'funcB']
<module 'fff' from 'x.py'>
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'funcA', 'funcB']
<module 'fff' from 'y.py'>
funcA of x.py
funcB of y.py
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'funcA', 'funcB']

我的预期是第二个imp.load_source将完全用 y.py 替换模块 x.py。事实上sys.modules.get('fff')显示<module 'fff' from 'y.py'>但生成的模块就像 x.py 和 y.py 的混合体,后者具有优先权。

这是预期还是错误?

编辑:我的测试代码有错字。更新了结果。

最佳答案

这是预期的行为。
参见 http://docs.python.org/2/library/imp.html

imp.load_source(name, pathname[, file])

Load and initialize a module implemented as a Python source file and return its module object. If the module was already initialized, it will be initialized again. The name argument is used to create or access a module object.

由于您的第二个模块与第一个模块同名,它不会替换第一个模块,而是会合并到第一个模块中。

源码给了我们同样的答案。
imp 是内置模块,定义在import.c中.
我们看一下load_source

的定义
static PyObject *
load_source_module(char *name, char *pathname, FILE *fp)
{
......
m = PyImport_ExecCodeModuleEx(name, (PyObject *)co, pathname);
Py_DECREF(co);

return m;
}

它只是 PyImport_ExecCodeModuleEx 的包装器。

PyObject *
PyImport_ExecCodeModuleEx(char *name, PyObject *co, char *pathname)
{
PyObject *modules = PyImport_GetModuleDict();
PyObject *m, *d, *v;

m = PyImport_AddModule(name);
......
d = PyModule_GetDict(m);
......
v = PyEval_EvalCode((PyCodeObject *)co, d, d);
......
}

现在,我们只需要关注 PyImport_AddModule。 Python 使用它来获取模块对象。您解析的源文件将放入此模块对象中。

PyObject *
PyImport_AddModule(const char *name)
{
PyObject *modules = PyImport_GetModuleDict();
PyObject *m;

if ((m = PyDict_GetItemString(modules, name)) != NULL &&
PyModule_Check(m))
return m;
m = PyModule_New(name);
if (m == NULL)
return NULL;
if (PyDict_SetItemString(modules, name, m) != 0) {
Py_DECREF(m);
return NULL;
}
Py_DECREF(m); /* Yes, it still exists, in modules! */

return m;
}

终于,我们找到了答案。给定一个name,如果某个模块已经有这个name,即name in sys.modules,Python不会创建新模块,但会重用该模块。

关于python - 通过 imp.load_source 加载具有相同名称的模块导致模块合并,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15082857/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com