Python: override __str__ in an exception instance

2024/9/23 13:22:03

I'm trying to override the printed output from an Exception subclass in Python after the exception has been raised and I'm having no luck getting my override to actually be called.

def str_override(self):"""Override the output with a fixed string"""return "Override!"def reraise(exception):"""Re-raise an exception and override its output"""exception.__str__ = types.MethodType(str_override, exception, type(exception))# Re-raise and remove ourselves from the stack trace.raise exception, None, sys.exc_info()[-1]def test():"""Should output "Override!" Actually outputs "Bah Humbug""""try:try:raise Exception("Bah Humbug")except Exception, e:reraise(e, "Said Scrooge")except Exception, e:print e

Any idea why this doesn't actually override the str method? Introspecting the instance variables shows that the method is actually overridden with the method but it's like Python just refuses to call it through print.

What am I missing here?

Answer

The problem is not that __str__() doesn't get overriden (just like you've already said, it does), but rather that str(e) (which invisibly gets called by print) is not always equivalent to e.__str__(). More specifically, if I get it right, str() (and other special methods, such as repr()), won't look for str in the instance dictionary - it would only look for it in the class dictionary. At least that is the case for the so-called new-style classes (which are the only classes in Python 3.x IIRC). You can read more about it here:

http://mail.python.org/pipermail/python-bugs-list/2005-December/031438.html

If you want to change the exception error message for a reraised exception, you can do something like this instead:

def reraise(exception):"""Re-raise an exception and override its output"""exType = type(exception)newExType = type(exType.__name__ + "_Override", (exType,), { '__str__': str_override})exception.__class__ = newExType# Re-raise and remove ourselves from the stack trace.raise exception, None, sys.exc_info()[-1]

This will dynamically derive a new exception class with the str override, and change exception to be an instance of that class. Now your code should work.

https://en.xdnf.cn/q/71819.html

Related Q&A

How hide/show a field upon selection of a radio button in django admin?

models.pyfrom django.db import models from django.contrib.auth.models import UserSTATUS_CHOICES = ((1, Accepted),(0, Rejected),) class Leave(models.Model):----------------status = models.IntegerField(c…

format/round numerical legend label in GeoPandas

Im looking for a way to format/round the numerical legend labels in those maps produced by .plot() function in GeoPandas. For example:gdf.plot(column=pop2010, scheme=QUANTILES, k=4)This gives me a lege…

Python pickle crash when trying to return default value in __getattr__

I have a dictionary like class that I use to store some values as attributes. I recently added some logic(__getattr__) to return None if an attribute doesnt exist. As soon as I did this pickle crashe…

How to download google source code for android

As you know, there is a list of several hundred projects in https://android.googlesource.com/. Id like to download them all in windows machine. According to Googles document,To install, initialize, and…

Compute on pandas dataframe concurrently

Is it feasible to do multiple group-wise calculation in dataframe in pandas concurrently and get those results back? So, Id like to compute the following sets of dataframe and get those results one-by…

How do I go about writing a program to send and receive sms using python?

I have looked all over the net for a good library to use in sending and receiving smss using python but all in vain!Are there GSM libraries for python out there?

Persist Completed Pipeline in Luigi Visualiser

Im starting to port a nightly data pipeline from a visual ETL tool to Luigi, and I really enjoy that there is a visualiser to see the status of jobs. However, Ive noticed that a few minutes after the l…

How to assign python requests sessions for single processes in multiprocessing pool?

Considering the following code example:import multiprocessing import requestssession = requests.Session() data_to_be_processed = [...]def process(arg):# do stuff with arg and get urlresponse = session.…

Missing values in Pandas Pivot table?

I have a data set that looks like the following:student question answer number Bob How many donuts in a dozen? A 1 Sally How many donuts in a do…

Selecting Element followed by text with Selenium WebDriver

I am using Selenium WebDriver and the Python bindings to automate some monotonous WordPress tasks, and it has been pretty straightforward up until this point. I am trying to select a checkbox, but the …