<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress/2.2.3" -->
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>
<channel>
	<title>Comments on: Re-raising Exceptions</title>
	<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/</link>
	<description></description>
	<pubDate>Thu, 28 Aug 2008 08:41:52 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.2.3</generator>

	<item>
		<title>By: Holger</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-28325</link>
		<dc:creator>Holger</dc:creator>
		<pubDate>Tue, 19 Aug 2008 09:08:50 +0000</pubDate>
		<guid>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-28325</guid>
		<description>Very helpful discussion. A Late comment:

The issue of re-raising base Exception instead of the original exception to avoid non-standard exception class constructors (like e.g. UnicodeEncodeError) could be addressed by dynamically creating a derived exception class:

    def reraise(exc_info=(None, None, None), errorMsg=''):
        """Re-raise the latest exception given by exc_info tuple (as returned by
        sys.exc_info()) with additional errorMsg text.
        Exceptions with non-standard constructors get re-raised as derived
        exceptions, with recorded original error message and original traceback.
        Parameters:
            exc_info: (, , )
                tuple
            errorMsg: error message text to add to the exception error message
        """
        excClass, exc, tb = exc_info
        try:
            # re-raise original exception with added custom error message
            raise excClass, excClass("%s: %s" % (exc, errorMsg)), tb
        except TypeError:
            if excClass == TypeError:
                # original exception is TypeError, which has a standard constructor:
                # safe to re-raise this way
                raise excClass, excClass("%s: %s" % (exc, errorMsg)), tb

            # TypeError due to non-standard exception constructor 
            if issubclass(excClass, Exception):
                # raise derived exception class with added custom error message
                class CustomInfoException(excClass):
                    def __init__(self, info='', args=[]):
                        self._info = info
                        excClass.__init__(self, *args)

                    def __str__(self):
                        return "%s: %s" % (excClass.__str__(self), self._info)

                CustomInfoException.__name__ = excClass.__name__
                raise CustomInfoException, \
                      CustomInfoException(info=errorMsg, args=exc.args), tb
            else:
                # raise base Exception class with added original exception
                # message plus custom error message. Safe for old string exceptions.
                raise Exception, \
                      Exception("%s: %s: %s"
                                % (getattr(excClass, '__name__', excClass), exc or
                                   excClass, errorMsg)), tb

As a derived class, the re-raised exception would even be caught later on if a dedicated exception
handler for the original exception existed somewhere further up the call stack.

In action:

    &#62;&#62;&#62; a = u'\xe4'
    &#62;&#62;&#62; def foo(s):
     ...     try:
     ...             b = str(s)
     ...     except:
     ...             reraise(sys.exc_info(), "really common problem")
     ...
     &#62;&#62;&#62; foo(a)
     Traceback (most recent call last):
       File "", line 1, in ?
       File "", line 5, in foo
       File "", line 3, in foo
     __main__.UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 0: ordinal
     not in range(128): really common problem
    &#62;&#62;&#62;</description>
		<content:encoded><![CDATA[<p>Very helpful discussion. A Late comment:</p>

<p>The issue of re-raising base Exception instead of the original exception to avoid non-standard exception class constructors (like e.g. UnicodeEncodeError) could be addressed by dynamically creating a derived exception class:</p>

<pre><code>def reraise(exc_info=(None, None, None), errorMsg=''):
    """Re-raise the latest exception given by exc_info tuple (as returned by
    sys.exc_info()) with additional errorMsg text.
    Exceptions with non-standard constructors get re-raised as derived
    exceptions, with recorded original error message and original traceback.
    Parameters:
        exc_info: (, , )
            tuple
        errorMsg: error message text to add to the exception error message
    """
    excClass, exc, tb = exc_info
    try:
        # re-raise original exception with added custom error message
        raise excClass, excClass("%s: %s" % (exc, errorMsg)), tb
    except TypeError:
        if excClass == TypeError:
            # original exception is TypeError, which has a standard constructor:
            # safe to re-raise this way
            raise excClass, excClass("%s: %s" % (exc, errorMsg)), tb

        # TypeError due to non-standard exception constructor 
        if issubclass(excClass, Exception):
            # raise derived exception class with added custom error message
            class CustomInfoException(excClass):
                def __init__(self, info='', args=[]):
                    self._info = info
                    excClass.__init__(self, *args)

                def __str__(self):
                    return "%s: %s" % (excClass.__str__(self), self._info)

            CustomInfoException.__name__ = excClass.__name__
            raise CustomInfoException, \
                  CustomInfoException(info=errorMsg, args=exc.args), tb
        else:
            # raise base Exception class with added original exception
            # message plus custom error message. Safe for old string exceptions.
            raise Exception, \
                  Exception("%s: %s: %s"
                            % (getattr(excClass, '__name__', excClass), exc or
                               excClass, errorMsg)), tb
</code></pre>

<p>As a derived class, the re-raised exception would even be caught later on if a dedicated exception
handler for the original exception existed somewhere further up the call stack.</p>

<p>In action:</p>

<pre><code>&amp;gt;&amp;gt;&amp;gt; a = u'\xe4'
&amp;gt;&amp;gt;&amp;gt; def foo(s):
 ...     try:
 ...             b = str(s)
 ...     except:
 ...             reraise(sys.exc_info(), "really common problem")
 ...
 &amp;gt;&amp;gt;&amp;gt; foo(a)
 Traceback (most recent call last):
   File "", line 1, in ?
   File "", line 5, in foo
   File "", line 3, in foo
 __main__.UnicodeEncodeError: 'ascii' codec can't encode character u'\xe4' in position 0: ordinal
 not in range(128): really common problem
&amp;gt;&amp;gt;&amp;gt;
</code></pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Hogarty</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-16243</link>
		<dc:creator>David Hogarty</dc:creator>
		<pubDate>Wed, 26 Mar 2008 18:45:44 +0000</pubDate>
		<guid>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-16243</guid>
		<description>Ian, was just attempting to use the 'add message' recipe, and found it had a type error:

    except Exception, exc:
        args = exc.args
        if not args:
            arg0 = ''
        else:
            arg0 = args[0]
        arg0 += ' at line %s' % lineno
        exc.args = arg0 + args[1:]
        raise

the second to last line should be 

    exc.args = (arg0,) + args[1:]

Here's a slightly more worked-out example, maybe a little over-functional 
in style, but it's flexible. With the `prepend_exc_str` function
(defined later), you can do:

    def prepend():
        try:
            dummy = b # throws NameError
        except Exception, exc:
            prepend_exc_str(exc, 'Message: ')
            raise
    prepend()

and get the result:

    Traceback (most recent call last):
      File "msg_add.py", line 44, in ?
        prepend()
      File "msg_add.py", line 31, in prepend
        dummy = b # throws NameError
    NameError: Message: global name 'b' is not defined

Here's the code, ready to change for other forms of message modification:

    def prepend_str(main, str):
        return str + main

    def append_str(main, str):
        return main + str

    def modify_exc_str_func(func):
        def inner_func(exc, str):
            # modifies exception in-place, so no return value
            # based on original by Ian Bicking:
            # http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/
            args = exc.args
            if not args:
                arg0 = ''
            else: arg0 = args[0]
            arg0 = func(arg0, str)
            exc.args = (arg0,) + args[1:]
        return inner_func
            
    prepend_exc_str = modify_exc_str_func(prepend_str)
    append_exc_str = modify_exc_str_func(append_str)</description>
		<content:encoded><![CDATA[<p>Ian, was just attempting to use the &#8216;add message&#8217; recipe, and found it had a type error:</p>

<pre><code>except Exception, exc:
    args = exc.args
    if not args:
        arg0 = ''
    else:
        arg0 = args[0]
    arg0 += ' at line %s' % lineno
    exc.args = arg0 + args[1:]
    raise
</code></pre>

<p>the second to last line should be </p>

<pre><code>exc.args = (arg0,) + args[1:]
</code></pre>

<p>Here&#8217;s a slightly more worked-out example, maybe a little over-functional 
in style, but it&#8217;s flexible. With the <code>prepend_exc_str</code> function
(defined later), you can do:</p>

<pre><code>def prepend():
    try:
        dummy = b # throws NameError
    except Exception, exc:
        prepend_exc_str(exc, 'Message: ')
        raise
prepend()
</code></pre>

<p>and get the result:</p>

<pre><code>Traceback (most recent call last):
  File "msg_add.py", line 44, in ?
    prepend()
  File "msg_add.py", line 31, in prepend
    dummy = b # throws NameError
NameError: Message: global name 'b' is not defined
</code></pre>

<p>Here&#8217;s the code, ready to change for other forms of message modification:</p>

<pre><code>def prepend_str(main, str):
    return str + main

def append_str(main, str):
    return main + str

def modify_exc_str_func(func):
    def inner_func(exc, str):
        # modifies exception in-place, so no return value
        # based on original by Ian Bicking:
        # &lt;a href="http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/" rel="nofollow"&gt;http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/&lt;/a&gt;
        args = exc.args
        if not args:
            arg0 = ''
        else: arg0 = args[0]
        arg0 = func(arg0, str)
        exc.args = (arg0,) + args[1:]
    return inner_func

prepend_exc_str = modify_exc_str_func(prepend_str)
append_exc_str = modify_exc_str_func(append_str)
</code></pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: David Hogarty</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-16242</link>
		<dc:creator>David Hogarty</dc:creator>
		<pubDate>Wed, 26 Mar 2008 18:39:23 +0000</pubDate>
		<guid>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-16242</guid>
		<description>(accidental double post, sorry)</description>
		<content:encoded><![CDATA[<p>(accidental double post, sorry)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Rafał Dowgird</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-925</link>
		<dc:creator>Rafał Dowgird</dc:creator>
		<pubDate>Fri, 14 Sep 2007 17:45:23 +0000</pubDate>
		<guid>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-925</guid>
		<description>Re: Traceback as an instance variable in exceptions

Traceback as an instance variable is a good start, combined with an optional 'cause exception' instance variable would practically yield the Java solution. Well, this and support in the 'language culture' - making people actually use it :-)</description>
		<content:encoded><![CDATA[<p>Re: Traceback as an instance variable in exceptions</p>

<p>Traceback as an instance variable is a good start, combined with an optional &#8217;cause exception&#8217; instance variable would practically yield the Java solution. Well, this and support in the &#8216;language culture&#8217; - making people actually use it :-)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ian Bicking</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-922</link>
		<dc:creator>Ian Bicking</dc:creator>
		<pubDate>Fri, 14 Sep 2007 17:20:08 +0000</pubDate>
		<guid>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-922</guid>
		<description>`tb_next` can be used to walk through the frames of the traceback; the traceback object looks kind of like a linked list of calling frames.</description>
		<content:encoded><![CDATA[<p><code>tb_next</code> can be used to walk through the frames of the traceback; the traceback object looks kind of like a linked list of calling frames.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ross Patterson</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-921</link>
		<dc:creator>Ross Patterson</dc:creator>
		<pubDate>Fri, 14 Sep 2007 17:12:12 +0000</pubDate>
		<guid>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-921</guid>
		<description>Re: Adding information to exceptions/Java

Would the [tb_next](http://docs.python.org/ref/types.html#traceback "Python Language Reference") attribute of traceback objects serve this purpose?

Ross</description>
		<content:encoded><![CDATA[<p>Re: Adding information to exceptions/Java</p>

<p>Would the <a href="http://docs.python.org/ref/types.html#traceback" title="Python Language Reference">tb_next</a> attribute of traceback objects serve this purpose?</p>

<p>Ross</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: nex</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-918</link>
		<dc:creator>nex</dc:creator>
		<pubDate>Fri, 14 Sep 2007 16:11:40 +0000</pubDate>
		<guid>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-918</guid>
		<description>Thanks for the quick reply, Ian! Now I know why my suspicion was dumb. I got confused when you mentioned recovering from unexpected errors. Is there actually a way to recover from the error (then it can't be unexpected, as we did anticipate it, and we should have explicitly declared which error we're trying to recover from), or is the program going to abort with failure anyways? I don't think the latter case is what "What Not To Do When Writing Python Software" was talking about, and when people use ``except:`` in that latter case, they're most often doing it wrong.

Then again, this is exactly what you're tackling here, teaching people how to do it **right**. So, all is well; but I think my confusion is excusable, since re-raising actually doesn't necessarily imply that you're dealing with a catastrophic failure and are going to abort without an attempt of recovery. That's just one case. (Another case, for example, would be guarding against a _specific_ error, trying to handle it, and having the error handling fail. I can think of more examples, but I'm sure you can do so as well.)</description>
		<content:encoded><![CDATA[<p>Thanks for the quick reply, Ian! Now I know why my suspicion was dumb. I got confused when you mentioned recovering from unexpected errors. Is there actually a way to recover from the error (then it can&#8217;t be unexpected, as we did anticipate it, and we should have explicitly declared which error we&#8217;re trying to recover from), or is the program going to abort with failure anyways? I don&#8217;t think the latter case is what &#8220;What Not To Do When Writing Python Software&#8221; was talking about, and when people use <code>except:</code> in that latter case, they&#8217;re most often doing it wrong.</p>

<p>Then again, this is exactly what you&#8217;re tackling here, teaching people how to do it <strong>right</strong>. So, all is well; but I think my confusion is excusable, since re-raising actually doesn&#8217;t necessarily imply that you&#8217;re dealing with a catastrophic failure and are going to abort without an attempt of recovery. That&#8217;s just one case. (Another case, for example, would be guarding against a <em>specific</em> error, trying to handle it, and having the error handling fail. I can think of more examples, but I&#8217;m sure you can do so as well.)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Kumar McMillan</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-917</link>
		<dc:creator>Kumar McMillan</dc:creator>
		<pubDate>Fri, 14 Sep 2007 15:21:01 +0000</pubDate>
		<guid>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-917</guid>
		<description>Cascading tracebacks is an interesting idea.  I wonder if it would be annoying or useful if you actually saw each traceback, terminating at the spots you had caught/re-raised.  In the current one-traceback world of Python, life is simpler, but in those rare cases where an exception is raised in your exception-handling code then you might as well be writing PHP4: you have to retrace your steps, uncomment stuff, etc, before you can figure out the root cause.  Of course one could hand-code cascading tracebacks with the `traceback.print_exc()` recipe above but if there was a way to make python do this automatically that might be useful.</description>
		<content:encoded><![CDATA[<p>Cascading tracebacks is an interesting idea.  I wonder if it would be annoying or useful if you actually saw each traceback, terminating at the spots you had caught/re-raised.  In the current one-traceback world of Python, life is simpler, but in those rare cases where an exception is raised in your exception-handling code then you might as well be writing PHP4: you have to retrace your steps, uncomment stuff, etc, before you can figure out the root cause.  Of course one could hand-code cascading tracebacks with the <code>traceback.print_exc()</code> recipe above but if there was a way to make python do this automatically that might be useful.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Ian Bicking</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-915</link>
		<dc:creator>Ian Bicking</dc:creator>
		<pubDate>Fri, 14 Sep 2007 15:07:28 +0000</pubDate>
		<guid>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-915</guid>
		<description>nex: when you respond to something after only skimming the article, you run the risk of looking dumb.  Like now.  When you *re-raise* an exception, you are looking for *unexpected* exceptions.  You don't know what the exception is.  And you don't have to swallow it, that's exactly what I'm showing in this article.

re: Java -- I believe (maybe only in py3k...?) that the traceback object is being added as an instance variable in the exception, which will probably make this all easier, and similar to in Java.</description>
		<content:encoded><![CDATA[<p>nex: when you respond to something after only skimming the article, you run the risk of looking dumb.  Like now.  When you <em>re-raise</em> an exception, you are looking for <em>unexpected</em> exceptions.  You don&#8217;t know what the exception is.  And you don&#8217;t have to swallow it, that&#8217;s exactly what I&#8217;m showing in this article.</p>

<p>re: Java &#8212; I believe (maybe only in py3k&#8230;?) that the traceback object is being added as an instance variable in the exception, which will probably make this all easier, and similar to in Java.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Brian Clapper</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-914</link>
		<dc:creator>Brian Clapper</dc:creator>
		<pubDate>Fri, 14 Sep 2007 14:52:12 +0000</pubDate>
		<guid>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-914</guid>
		<description>_Adding information to exceptions has been very nicely implemented in Java - you can pass the original exception to your exception’s constructor and get a chained stack trace. Flame away, but I think that Java beats Python in this area ._

That feature showed up in Java in the 1.4 release, I believe. It wasn't there originally; I know, because I had to implement it myself before Java 1.4 was out. It's also not a feature of the language, per se; it's a feature of how the exception library classes are written. Seems to me that one could add the capability of nested, or wrapped, exceptions to Python easily enough.

It *is* a useful solution to the problem, because you get tracebacks for everything in the chain of nested exceptions. A little verbose at times, but a useful compromise.</description>
		<content:encoded><![CDATA[<p><em>Adding information to exceptions has been very nicely implemented in Java - you can pass the original exception to your exception’s constructor and get a chained stack trace. Flame away, but I think that Java beats Python in this area .</em></p>

<p>That feature showed up in Java in the 1.4 release, I believe. It wasn&#8217;t there originally; I know, because I had to implement it myself before Java 1.4 was out. It&#8217;s also not a feature of the language, per se; it&#8217;s a feature of how the exception library classes are written. Seems to me that one could add the capability of nested, or wrapped, exceptions to Python easily enough.</p>

<p>It <em>is</em> a useful solution to the problem, because you get tracebacks for everything in the chain of nested exceptions. A little verbose at times, but a useful compromise.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
