擅长:python、mysql、java
<p>这种情况与类似的出现案例(如<code>super</code>)之间的区别在于,这里没有可查看的封闭框架。<code>with</code>语句不是新范围。<code>sys._getframe(0)</code>(或者,如果您将代码放入函数中,<code>sys._getframe(1)</code>)可以正常工作,但它将返回与<code>with</code>语句前后相同的帧。在</p>
<p>唯一的方法就是检查字节码。但即使这样也无济于事。例如,请尝试以下操作:</p>
<pre><code>from contextlib import contextmanager
@contextmanager
def silly():
yield
with silly():
fr = sys._getframe(0)
dis.dis(fr.f_code)
</code></pre>
<p>显然,正如<a href="http://docs.python.org/3/library/dis.html#opcode-SETUP_WITH" rel="nofollow">^{<cd6>}</a>所解释的那样,该方法确实会被查找并推送到堆栈上,供<a href="http://docs.python.org/3/library/dis.html#opcode-WITH_CLEANUP" rel="nofollow">^{<cd7>}</a>以后使用。因此,即使<code>POP_TOP</code>删除了<code>silly()</code>的返回值,它的<code>__exit__</code>仍然在堆栈中。在</p>
<p>从Python那里走不到那里。除非您想开始咀嚼字节码,或者用<code>ctypes</code>或其他东西来挖掘堆栈,否则它可能不存在。在</p>