浏览logging
模块并看到以下内容:
# next bit filched from 1.5.2's inspect.py
def currentframe():
"""Return the frame object for the caller's stack frame."""
try:
raise Exception
except:
return sys.exc_info()[2].tb_frame.f_back
if hasattr(sys, '_getframe'): currentframe = lambda: sys._getframe(3)
# done filching
在这种情况下,“过滤”一词是什么意思?
答案 0 :(得分:3)
这是您不希望作为示例的代码!首先,它特定于CPython实现,因此无法在PyPy,Jython,Iron Python等环境下使用。
我认为作者提出了异常,以便访问调用例程的堆栈框架,或者可能是调用者的调用者。
“ Filching”未经许可即被盗用,因此这只是一种内的表达方式:“我是从开源库复制并粘贴的。”
答案 1 :(得分:2)
作为barny commented的注释内容为:
# next bit filched from 1.5.2's inspect.py
使用该词来表示“复制自”。也就是说,从Python版本1.5.2开始,这种特殊的代码序列已经存在了很长时间。
这里的正在进行是什么(编辑:问题的这一部分已被删除!)很简单但很微妙。任何异常都会导致Python系统找到最内部的当前活动except
处理程序。在这种情况下,这是下一行—
try:
raise Exception
except:
...
直接进入...
行。但是,raise
具有副作用,这是整件事的关键。副作用是raise
使 traceback堆栈包含指向最近的{sup> 1 指向raise
行的执行状态本身。
sys.exc_info()
函数返回一个包含三个元素的元组:异常的类型,异常的值(此处未传递值,因为处理程序不需要一个值)和(整个)回溯堆栈。 [2]
从元组中提取此追溯堆栈,并丢弃异常类型和值。
回溯栈的结构有些复杂,但是每个回溯栈实例中都有一个.tb_frame
属性。它包含有关发生异常时处于活动状态的堆栈帧的信息。由于这是函数激活的堆栈,因此它的前身是在调用currentframe
时处于活动状态,因此这是调用者的框架。
这种定位调用方框架的方法不是很有效(并且,holdenweb points out特定于CPython解释器),因此,如果sys
具有_getframe
函数,则文件-绑定currentframe
以调用sys._getframe(3)
。 (我不确定常数3在这里做什么,因为另一个版本有效地返回了sys._getframe(0)
将返回的内容。编辑2:在进一步检查时,魔术常数3负责调用{{1}的日志处理程序。 }会调用_log
,这又会调用findCaller
。这是另一种效率攻击,因为currentframe
会在每个堆栈帧中向上爬,以查找在文件而非中出现的一个日志模块的代码本身。这样会更好。)
1 请记住,堆栈是任何以后进先出(LIFO)方式运行的数据结构。 Python解释器管理一堆不同的(或多或少)同时的堆栈,包括异常处理程序和常规的函数调用机制。