
不幸的是,正如评论中所讨论的,这并非在所有情况下都是可行的。创建上下文管理器后,将运行以下代码(至少在cPython
2.7中运行。我无法评论其他实现):
case SETUP_WITH: { static PyObject *exit, *enter; w = TOP(); x = special_lookup(w, "__exit__", &exit); if (!x) break; SET_TOP(x); }该
__exit__方法与
SET_TOP宏一起被压入堆栈,该宏定义为:
#define SET_TOP(v) (stack_pointer[-1] = (v))
依次将堆栈指针设置为帧eval开始时帧值堆栈的顶部:
stack_pointer = f->f_stacktop;
其中f是frameobject.h中定义的框架对象。对于我们来说不幸的是,这就是小路的终点。只能通过以下方法定义python可访问框架对象:
static PyMemberDef frame_memberlist[] = { {"f_back", T_OBJECT, OFF(f_back), RO}, {"f_pre", T_OBJECT, OFF(f_pre), RO}, {"f_builtins", T_OBJECT, OFF(f_builtins),RO}, {"f_globals", T_OBJECT, OFF(f_globals), RO}, {"f_lasti", T_INT, OFF(f_lasti), RO}, {NULL} };不幸的是,其中不包括
f_valuestack我们需要的东西。这是有道理的,因为
f_valuestack它的类型是
PyObject**,因此需要将其包装在一个对象中,以便可以以任何方式从python访问。
TL; DR:
__exit__我们要寻找的方法仅位于一个位置,即框架对象的值堆栈,而cPython并未使python代码可以访问该值堆栈。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)