<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Re-raising Exceptions</title>
	<atom:link href="http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/</link>
	<description></description>
	<lastBuildDate>Fri, 03 Sep 2010 01:53:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>By: Yuri Baburov</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/comment-page-1/#comment-147150</link>
		<dc:creator>Yuri Baburov</dc:creator>
		<pubDate>Tue, 12 Jan 2010 20:11:24 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-147150</guid>
		<description>Well, in simple cases, when you don&#039;t need to change message and just do re-raise,
you can use the simple `raise exc_info[1], None, exc_info[2]`

Your `raise exc_info[0], exc_info[1], exc_info[2]` is incorrect, at least, in Python 2.5!</description>
		<content:encoded><![CDATA[<p>Well, in simple cases, when you don&#8217;t need to change message and just do re-raise,
you can use the simple <code>raise exc_info[1], None, exc_info[2]</code></p>

<p>Your <code>raise exc_info[0], exc_info[1], exc_info[2]</code> is incorrect, at least, in Python 2.5!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Hari</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/comment-page-1/#comment-136203</link>
		<dc:creator>Hari</dc:creator>
		<pubDate>Mon, 02 Nov 2009 20:10:17 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-136203</guid>
		<description>Ooops... sorry, the logging call has a typo, it should be:

                logging.getLogger().error(&quot;Exception in cleanup ignored due to a pending exception on stack&quot;, exc_info=1)

or simply:

                logging.getLogger().exception(&quot;Exception in cleanup ignored due to a pending exception on stack&quot;)</description>
		<content:encoded><![CDATA[<p>Ooops&#8230; sorry, the logging call has a typo, it should be:</p>

<pre><code>            logging.getLogger().error("Exception in cleanup ignored due to a pending exception on stack", exc_info=1)
</code></pre>

<p>or simply:</p>

<pre><code>            logging.getLogger().exception("Exception in cleanup ignored due to a pending exception on stack")
</code></pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Hari</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/comment-page-1/#comment-136202</link>
		<dc:creator>Hari</dc:creator>
		<pubDate>Mon, 02 Nov 2009 20:07:54 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-136202</guid>
		<description>Paul, You can achieve the same with the following inline code:

    logging.getLogger(&quot;Exception ignored during finally&quot;, exc_info=1)

However, what I like to do in such a scenario is is to conditionally propagate the exception, something like this (for a db operation):

    success = 0
    try:
        do_db_operation()
        success = 1
    finally:
        if not success:
            try:
                do_rollback()
            except (KeyboardInterrupt, SystemExit):
                raise
            except:
                logging.getLogger(&quot;Exception in cleanup ignored due to a pending exception on stack&quot;, exc_info=1)
        else:
            do_commit()

The advantage is that if the db operation fails (say a constraint violation), then it does a rollback (while making sure to not stomp on the original exception), but when the operation succeeds, any exception in commit is taken seriously and so is propagated.</description>
		<content:encoded><![CDATA[<p>Paul, You can achieve the same with the following inline code:</p>

<pre><code>logging.getLogger("Exception ignored during finally", exc_info=1)
</code></pre>

<p>However, what I like to do in such a scenario is is to conditionally propagate the exception, something like this (for a db operation):</p>

<pre><code>success = 0
try:
    do_db_operation()
    success = 1
finally:
    if not success:
        try:
            do_rollback()
        except (KeyboardInterrupt, SystemExit):
            raise
        except:
            logging.getLogger("Exception in cleanup ignored due to a pending exception on stack", exc_info=1)
    else:
        do_commit()
</code></pre>

<p>The advantage is that if the db operation fails (say a constraint violation), then it does a rollback (while making sure to not stomp on the original exception), but when the operation succeeds, any exception in commit is taken seriously and so is propagated.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Holger</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/comment-page-1/#comment-42935</link>
		<dc:creator>Holger</dc:creator>
		<pubDate>Fri, 12 Sep 2008 08:16:34 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-42935</guid>
		<description>Correction:
issubclass() raises an error itself when fed with a non-class first argument, so reraise() should be:

    def reraise(exc_info=(None, None, None), errorMsg=&#039;&#039;):
        &quot;&quot;&quot;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: (&lt;exception class&gt;, &lt;exception instance&gt;, &lt;traceback object&gt;)
                tuple
            errorMsg: error message text to add to the exception error message
        &quot;&quot;&quot;
        excClass, exc, tb = exc_info
        try:
            # re-raise original exception with added custom error message
            raise excClass, excClass(&quot;%s: %s&quot; % (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(&quot;%s: %s&quot; % (exc, errorMsg)), tb

            # TypeError due to non-standard exception constructor 
            if isinstance(excClass, (types.ClassType, type)) \
               and issubclass(excClass, Exception):
                # raise derived exception class with added custom error message
                class CustomInfoException(excClass):
                    def __init__(self, info=&#039;&#039;, args=[]):
                        self._info = info
                        excClass.__init__(self, *args)

                    def __str__(self):
                        return &quot;%s: %s&quot; % (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(&quot;%s: %s: %s&quot;
                                % (getattr(excClass, &#039;__name__&#039;, excClass), exc or
                                   excClass, errorMsg)), tb
</description>
		<content:encoded><![CDATA[<p>Correction:
issubclass() raises an error itself when fed with a non-class first argument, so reraise() should be:</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: (&lt;exception class&gt;, &lt;exception instance&gt;, &lt;traceback object&gt;)
            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 isinstance(excClass, (types.ClassType, type)) \
           and 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>
]]></content:encoded>
	</item>
	<item>
		<title>By: Holger</title>
		<link>http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/comment-page-1/#comment-28325</link>
		<dc:creator>Holger</dc:creator>
		<pubDate>Tue, 19 Aug 2008 09:08:50 +0000</pubDate>
		<guid isPermaLink="false">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=&#039;&#039;):
        &quot;&quot;&quot;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
        &quot;&quot;&quot;
        excClass, exc, tb = exc_info
        try:
            # re-raise original exception with added custom error message
            raise excClass, excClass(&quot;%s: %s&quot; % (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(&quot;%s: %s&quot; % (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=&#039;&#039;, args=[]):
                        self._info = info
                        excClass.__init__(self, *args)

                    def __str__(self):
                        return &quot;%s: %s&quot; % (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(&quot;%s: %s: %s&quot;
                                % (getattr(excClass, &#039;__name__&#039;, 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:

    &gt;&gt;&gt; a = u&#039;\xe4&#039;
    &gt;&gt;&gt; def foo(s):
     ...     try:
     ...             b = str(s)
     ...     except:
     ...             reraise(sys.exc_info(), &quot;really common problem&quot;)
     ...
     &gt;&gt;&gt; foo(a)
     Traceback (most recent call last):
       File &quot;&quot;, line 1, in ?
       File &quot;&quot;, line 5, in foo
       File &quot;&quot;, line 3, in foo
     __main__.UnicodeEncodeError: &#039;ascii&#039; codec can&#039;t encode character u&#039;\xe4&#039; in position 0: ordinal
     not in range(128): really common problem
    &gt;&gt;&gt;</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-page-1/#comment-16243</link>
		<dc:creator>David Hogarty</dc:creator>
		<pubDate>Wed, 26 Mar 2008 18:45:44 +0000</pubDate>
		<guid isPermaLink="false">http://blog.ianbicking.org/2007/09/12/re-raising-exceptions/#comment-16243</guid>
		<description>Ian, was just attempting to use the &#039;add message&#039; recipe, and found it had a type error:

    except Exception, exc:
        args = exc.args
        if not args:
            arg0 = &#039;&#039;
        else:
            arg0 = args[0]
        arg0 += &#039; at line %s&#039; % lineno
        exc.args = arg0 + args[1:]
        raise

the second to last line should be 

    exc.args = (arg0,) + args[1:]

Here&#039;s a slightly more worked-out example, maybe a little over-functional 
in style, but it&#039;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, &#039;Message: &#039;)
            raise
    prepend()

and get the result:

    Traceback (most recent call last):
      File &quot;msg_add.py&quot;, line 44, in ?
        prepend()
      File &quot;msg_add.py&quot;, line 31, in prepend
        dummy = b # throws NameError
    NameError: Message: global name &#039;b&#039; is not defined

Here&#039;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 = &#039;&#039;
            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-page-1/#comment-16242</link>
		<dc:creator>David Hogarty</dc:creator>
		<pubDate>Wed, 26 Mar 2008 18:39:23 +0000</pubDate>
		<guid isPermaLink="false">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-page-1/#comment-925</link>
		<dc:creator>Rafał Dowgird</dc:creator>
		<pubDate>Fri, 14 Sep 2007 17:45:23 +0000</pubDate>
		<guid isPermaLink="false">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 &#039;cause exception&#039; instance variable would practically yield the Java solution. Well, this and support in the &#039;language culture&#039; - 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; &#8211; 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-page-1/#comment-922</link>
		<dc:creator>Ian Bicking</dc:creator>
		<pubDate>Fri, 14 Sep 2007 17:20:08 +0000</pubDate>
		<guid isPermaLink="false">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-page-1/#comment-921</link>
		<dc:creator>Ross Patterson</dc:creator>
		<pubDate>Fri, 14 Sep 2007 17:12:12 +0000</pubDate>
		<guid isPermaLink="false">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 &quot;Python Language Reference&quot;) 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>
</channel>
</rss>

<!-- Dynamic Page Served (once) in 1.920 seconds -->
