Exception problem with module

J

Joseph L. Casale

I am working with a module that I am seeing some odd behavior.

A module.foo builds a custom exception, module.foo.MyError, its done right
afaict.

Another module, module.bar imports this and calls bar.__setattr__('a_new_name', MyError).

Now, not in all but in some cases when I catch a_new_name, my code raises anew
exception:

During handling of the above exception, another exception occurred:

File "C:/dir/test.py", line 12, in <module>
except a_new_name as exc:
TypeError: catching classes that do not inherit from BaseException is not allowed

So, I wont suggest the assignment in bar added anything, nor would I do this, but
its what I am working with. Why might this happen? MyError subclasses Exception
and calls super passing back args.

This has something to do with the assignment in bar, catching MyError obviously works.

Any ideas?
jlc
 
S

Steven D'Aprano

I am working with a module that I am seeing some odd behavior.

A module.foo builds a custom exception, module.foo.MyError, its done
right afaict.

Another module, module.bar imports this and calls
bar.__setattr__('a_new_name', MyError).

I see that you've solved your immediate problem, but you shouldn't call
__setattr__ directly. That should actually be written

setattr(bar, 'a_new_name', MyError)

But really, since bar is (apparently) a module, and it is *bar itself*
setting the attribute, the better way is

a_new_name = MyError

or even

from module.foo import MyError as a_new_name
 
J

Joseph L. Casale

I see that you've solved your immediate problem, but you shouldn't call
__setattr__ directly. That should actually be written

setattr(bar, 'a_new_name', MyError)

But really, since bar is (apparently) a module, and it is *bar itself*
setting the attribute, the better way is

a_new_name = MyError

or even

from module.foo import MyError as a_new_name

Well I am not sure what advantage this has for the user, not my code as
I don't advocate the import to begin with it, its fine spelled as it was from
where it was... I'll look back at this and see if that resolves the issue as it
had manifested.

jlc
 
S

Steven D'Aprano

Well I am not sure what advantage this has for the user, not my code as
I don't advocate the import to begin with it, its fine spelled as it was
from where it was...

The advantage for the user is:

- it avoids module bar needing to get a reference to itself;

- it avoids the distraction of unnecessarily calling a dunder
method;

- it is idiomatic Python code that should be instantly
understandable by any even moderately experienced
Python coder;

- prevents the reader from puzzling over why the code does
something so unusual ("but why does he do this...?");

- and avoids the inevitable anger and/or contempt when the
reader works out that there is no good reason to write
such unidiomatic code.

One should code as if the next person who reads your program is an easily
upset psychotic axe-murderer who knows where you live. You wouldn't
condone writing y = x.__add__(1) instead of y = x + 1, you shouldn't
condone writing module.__setattr__ directly either.

I'll look back at this and see if that resolves the
issue as it had manifested.

I doubt it. Not unless module bar has done something weird, like define a
function called __setattr__ that shadows the actual method and wraps the
exception in another object. More likely, I think you'll find that the
original MyError doesn't inherit from Exception.
 
C

Chris Angelico

One should code as if the next person who reads your program is an easily
upset psychotic axe-murderer who knows where you live. You wouldn't
condone writing y = x.__add__(1) instead of y = x + 1, you shouldn't
condone writing module.__setattr__ directly either.

Oddly enough, I was referencing that first half earlier this evening :)

There's a difference between x.__add__(1) and x + 1, though. The
latter might end up calling (1).__radd__(x), which (obviously) the
first won't. I can imagine there might be some use-case where you
specifically DON'T want the reflected method to be silently called
(maybe for introspection or debugging??). But it falls under code
smell, the sort of thing where you absolutely MUST have a comment -
like where I have a call to set_foreground(bg), because that could so
easily be an error, yet in this case isn't.

ChrisA
 
J

Joseph L. Casale

Well I am not sure what advantage this has for the user, not my code as
The advantage for the user is:

/snip

Hey Steven,
Sorry for the late reply (travelling). My comment wasn't clear, I was ranting against
the import of the exception in the second module, non the less how it was imported
and not why it was not ok.

Basically, it was no better than leaving it where it was, spelled as it wasand
requiring the user to import it from where it was defined. It turned out tobe
some faulty logic in the second module where the __setattr__ call was made
that was preventing it from being set...

jlc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top