我一直在研究加载python(osx上的2.7)文件作为配置文件的一些案例.我想看看如果我循环运行execfile会有什么行为.我预计会出现内存不足错误或大量交换,但当我得到不同的结果时,我感到非常惊讶.
我设置了一个测试场景如下:
'd'python脚本:
#!/usr/bin/python
x = 0
execfile("d1")
Run Code Online (Sandbox Code Playgroud)
'd1'python脚本:
#!/usr/bin/python
x += 1
print "x = %d" % x
execfile("d2")
Run Code Online (Sandbox Code Playgroud)
'd2'python脚本:
#!/usr/bin/python
x += 1
print "x = %d" % x
execfile("d1")
Run Code Online (Sandbox Code Playgroud)
结果:
$ ./d
x = 1
x = 2
x = 3
... removed for brevity ...
x = 997
x = 998
x = 999
Traceback (most recent call last):
File "./d", line 5, in <module>
execfile("d1")
File "d1", line 5, in <module>
execfile("d2")
File "d2", line 5, in <module>
execfile("d1")
... removed for brevity ...
File "d1", line 5, in <module>
execfile("d2")
File "d2", line 5, in <module>
execfile("d1")
File "d1", line 5, in <module>
execfile("d2")
KeyError: 'unknown symbol table entry'
Run Code Online (Sandbox Code Playgroud)
我只是好奇是否有人可以解释这里发生的事情?为什么在执行execfile~1000次之后会停止?
从Python源代码,Objects/dictobject.c:
/* Note that, for historical reasons, PyDict_GetItem() suppresses all errors * that may occur (originally dicts supported only string keys, and exceptions * weren't possible). So, while the original intent was that a NULL return * meant the key wasn't present, in reality it can mean that, or that an error * (suppressed) occurred while computing the key's hash, or that some error * (suppressed) occurred when comparing keys in the dict's internal probe * sequence. A nasty example of the latter is when a Python-coded comparison * function hits a stack-depth error, which can cause this to return NULL * even if the key is present. */
因此,PyDict_GetItem()并不总是正确报告错误.有趣......所以在下面的代码中Python/symtable.c,
v = PyDict_GetItem(st->st_blocks, k);
if (v) {
assert(PySTEntry_Check(v));
Py_INCREF(v);
}
else {
PyErr_SetString(PyExc_KeyError,
"unknown symbol table entry");
}
Run Code Online (Sandbox Code Playgroud)
查找符号时出现的任何错误(包括内存不足错误)都将变为KeyError.这可能是一个错误.