我想知道是否存在以下行为或错误.我正在使用CPython2.7
创建一个x.py文件
def funcA():
print "funcA of x.py"
def funcB():
print "funcB of x.py"
Run Code Online (Sandbox Code Playgroud)
创建一个y.py文件
def funcB():
print "funcB of y.py"
Run Code Online (Sandbox Code Playgroud)
创建一个文件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)
Run Code Online (Sandbox Code Playgroud)
结果
['__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']
Run Code Online (Sandbox Code Playgroud)
我的期望是第二个imp.load_source完全用y.py代替模块x.py. 实际上sys.modules.get('fff')显示<module 'fff' from 'y.py'>但是生成的模块就像是x.py和y.py的混合,而后者具有优先权.
这是预期还是错误?
编辑:我的测试代码有一个错字.更新了结果.
nym*_*ymk 15
这是预期的行为.
见http://docs.python.org/2/library/imp.html
imp.load_source(name,pathname [,file])
加载并初始化实现为Python源文件的模块并返回其模块对象.如果模块已经初始化,它将再次初始化.name参数用于创建或访问模块对象.
由于您的第二个模块与第一个模块具有相同的名称,因此它不会替换第一个模块,而是将合并到第一个模块中.
源代码给出了相同的答案.
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;
}
Run Code Online (Sandbox Code Playgroud)
它只是一个包装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);
......
}
Run Code Online (Sandbox Code Playgroud)
现在,我们只需要关注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;
}
Run Code Online (Sandbox Code Playgroud)
最后,我们找到了答案.给定一个name,如果某个模块已经有了这个name,那么name in sys.modules,Python将不会创建一个新模块,而是会重用该模块.
| 归档时间: |
|
| 查看次数: |
12094 次 |
| 最近记录: |