How to check, whether exception was raisen in the current scope?
<p>I use the following code to call an arbitrary callable <code>f()</code> with appropriate number of parameters:</p>

<pre><code>try:
    res = f(arg1)
except TypeError:
    res = f(arg1, arg2)
</code></pre>

<p>If <code>f()</code> is a two parameter function, calling it with just one parameter raises <code>TypeError</code>, so the function can be called properly in the <code>except</code> branch.</p>

<p>The problem is when <code>f()</code> is one-parameter function and the exception is raisen in the body of <code>f()</code> (possibly because of a bad call to some function), for example:</p>

<pre><code>def f(arg):
    map(arg) # raises TypeError
</code></pre>

<p>The control flow goes to the <code>except</code> branch because of the internal error of <code>f()</code>. Of course calling <code>f()</code> with two arguments raises a new <code>TypeError</code>. Then instead of traceback to the original error I get traceback to the call of <code>f()</code> with two parameters, which is much less helpful when debugging.</p>

<p>How can my code recognize exceptions raised not in the current scope to reraise them?</p>

<p>I want to write the code like this:</p>

<pre><code>try:
    res = f(arg1)
except TypeError:
    if exceptionRaisedNotInTheTryBlockScope(): # &lt;-- subject of the question
        raise
    res = f(arg1, arg2)
</code></pre>

<p>I know I can use a walkarround by adding <code>exc_info = sys.exc_info()</code> in the <code>except</code> block.</p>

<p>One of assumptions is I have no control over <code>f()</code> since it is given by user of my module. Also its <code>__name__</code> attribute may be other than <code>'f'</code>. Internal exception may be raised by bad recurrent call to <code>f()</code>.
The walkarround is unsuitable since it complicates debugging by the author of <code>f()</code>.</p>

<p>Finally figured it out:</p>

<pre><code>def exceptionRaisedNotInTheTryBlockScope():
    return sys.exc_info()[2].tb_next is not None
</code></pre>

<p><code>sys.exc_info()</code> returns a 3-element <code>tuple</code>. Its last element is the traceback of the last exception. If the traceback object is the only one in the traceback chain, then the exception has been raisen in the scope of the <code>try</code> block (<a href="https://docs.python.org/2/reference/datamodel.html" rel="nofollow">https://docs.python.org/2/reference/datamodel.html</a>).</p>

<p>According to <a href="https://docs.python.org/2/library/sys.html#sys.exc_info" rel="nofollow">https://docs.python.org/2/library/sys.html#sys.exc_info</a>, it should be avoided to store the traceback value.</p>

python python-2.7 python-3.x debugging exception-handling