catching my own exception

N

nick

I have a problem with catching my own exception. Here is the code:
http://fly.srk.fer.hr/~nick/travapi/blame.php?repname=Travian+API&path=/village.py&

Line 252 calls a method, which on line 207 raises a
SomethingBeingBuiltError exception. On line 253 I catch that
exception, but when I run that code, I get:

Traceback (most recent call last):
File "village.py", line 252, in <module>
v.upgrade_cheapest()
File "/media/data/home/code/travapi/village.py", line 207, in upgrade_cheapest
raise SomethingBeingBuiltError()
village.SomethingBeingBuiltError: 'Unable to upgrade, check if something is being built.'

If I change line 253 to only "except:", everything works as
expected. How come? What am I missing? Any help would be appreciated.

P.S.: I'm aware I'm exposing my login/pass in the code. Don't care
really, those are throwaway accounts.
 
J

Jon Clements

I have a problem with catching my own exception. Here is the code:http://fly.srk.fer.hr/~nick/travapi/blame.php?repname=Travian+API&pat...

Line 252 calls a method, which on line 207 raises a
SomethingBeingBuiltError exception. On line 253 I catch that
exception, but when I run that code, I get:

Traceback (most recent call last):
  File "village.py", line 252, in <module>
    v.upgrade_cheapest()
  File "/media/data/home/code/travapi/village.py", line 207, in upgrade_cheapest
    raise SomethingBeingBuiltError()
village.SomethingBeingBuiltError: 'Unable to upgrade, check if something is being built.'

If I change line 253 to only "except:", everything works as
expected. How come? What am I missing? Any help would be appreciated.

P.S.: I'm aware I'm exposing my login/pass in the code. Don't care
really, those are throwaway accounts.

--
"Now the storm has passed over me
I'm left to drift on a dead calm sea
And watch her forever through the cracks in the beams
Nailed across the doorways of the bedrooms of my dreams"

http://www.travian.com/spielregeln.php -- rule 3???
 
S

Steven D'Aprano

I have a problem with catching my own exception. Here is the code:
http://fly.srk.fer.hr/~nick/travapi/blame.php?repname=Travian+API&path=% 2Fvillage.py&

Line 252 calls a method, which on line 207 raises a
SomethingBeingBuiltError exception. On line 253 I catch that exception,
but when I run that code, I get:

Traceback (most recent call last):
File "village.py", line 252, in <module>
v.upgrade_cheapest()
File "/media/data/home/code/travapi/village.py", line 207, in
upgrade_cheapest
raise SomethingBeingBuiltError()
village.SomethingBeingBuiltError: 'Unable to upgrade, check if something
is being built.'

If I change line 253 to only "except:", everything works as expected.
How come? What am I missing? Any help would be appreciated.


I can't run your code, so I'm stuck with trying to guess how it works
just by reading it. As far as I can tell, it should work. If it doesn't
work, I can only imagine that you're not running the code you think you
are running. Perhaps you're running an older version?


Other than that, I notice that your module throws away useful debugging
information, and replaces it with bland, useless pap of no nutritional
value:

try:
import account, fetch, resources, const
except Exception:
raise Exception('One or more travapi modules not available.')

Instead of a useful ImportError exception that tells the caller two
important pieces of information (namely that it is an import error, and
what the error actually was) you replace it with a useless, generic
error. It might as well say "An error occurred" for all the use it is.

Errors should be *more* specific, not less. By replacing useful, specific
exceptions with the generic Exception class, you're throwing information
away and making your own job harder. Why would you rather see:

Exception: One or more travapi modules not available.

instead of this?

ImportError: No module named resources

As a general rule, anytime you find yourself writing:

except SomeSpecificException:
raise SomeOtherException

you should stop and think *really hard* about why you are bothering.
 
P

Peter Otten

nick said:
I have a problem with catching my own exception. Here is the code:
http://fly.srk.fer.hr/~nick/travapi/blame.php?repname=Travian+API&path=/village.py&

Line 252 calls a method, which on line 207 raises a
SomethingBeingBuiltError exception. On line 253 I catch that
exception, but when I run that code, I get:

Traceback (most recent call last):
File "village.py", line 252, in <module>
v.upgrade_cheapest()
File "/media/data/home/code/travapi/village.py", line 207, in
upgrade_cheapest
raise SomethingBeingBuiltError()
village.SomethingBeingBuiltError: 'Unable to upgrade, check if something
is being built.'

If I change line 253 to only "except:", everything works as
expected. How come? What am I missing? Any help would be appreciated.

P.S.: I'm aware I'm exposing my login/pass in the code. Don't care
really, those are throwaway accounts.

You are importing your main script elswhere. Your code then
effectively becomes

try:
# in another module
raise village.SomethingBuiltError
except __main__.SomethingBeingBuiltError:
print "caught"

i. e. you get two versions of every class that are built from the same code
but not (recognized as) identical.

Solution: move your startup code into a separate file and have it import the
village module.

Peter
 
N

Nikola Skoric

Dana Fri, 18 Jun 2010 20:01:45 +0200,
Peter Otten said:
Solution: move your startup code into a separate file and have it import the
village module.

Excellent, thanks! Everything works now, but I still don't quite get what the problem is...
You are importing your main script elswhere. Your code then
effectively becomes

try:
# in another module
raise village.SomethingBuiltError
except __main__.SomethingBeingBuiltError:
print "caught"

i. e. you get two versions of every class that are built from the same code
but not (recognized as) identical.

What I don't get is: what do you mean I'm importing my main script
elsewhere by runing "python village.py"? SomethingBuiltError is
defined in the same script that I'm runing, I didn't import it, did I?
If you could please clear it up for me... or point me to relevant
literature, that's also cool, I couldn't find this thing explained
anywhere.

Anyway, thanks for the solution!
 
N

Nikola Skoric

Dana 18 Jun 2010 17:45:31 GMT,
Steven D'Aprano said:
Other than that, I notice that your module throws away useful debugging
information, and replaces it with bland, useless pap of no nutritional
value:

try:
import account, fetch, resources, const
except Exception:
raise Exception('One or more travapi modules not available.')

Oh, yes, thanks for pointing that out, that was a dirty hack for
solving some error I was getting with pydoc. I'll remove that, thanks
for pointing that out.
 
P

Peter Otten

Nikola said:
Dana Fri, 18 Jun 2010 20:01:45 +0200,


Excellent, thanks! Everything works now, but I still don't quite get what
the problem is...


What I don't get is: what do you mean I'm importing my main script
elsewhere by runing "python village.py"? SomethingBuiltError is
defined in the same script that I'm runing, I didn't import it, did I?
If you could please clear it up for me... or point me to relevant
literature, that's also cool, I couldn't find this thing explained
anywhere.

In Python, if you write

class A:
pass

that is executable code just like an if-statement or a for-loop rather than
a declaration, and this code creates a new class every time it is run.
That's why
.... class A: pass
.... items.append(A)
....
issubclass(A, A) True
issubclass(items[0], items[1])
False

creates 5 distinct classes. The same would go for modules if it weren't for
the sys.modules cache:

If we clear the cache manually, the code in the module will be executed
again:
import sys
del sys.modules["tmp"]
import tmp
importing tmp

Now in your case village.py is first run as the main script and then
imported from within account.py -- but the main script is put into the cache
under the key "__main__" regardless of its actual name. Using our simple
example:

$ python -i tmp.py
importing __main__importing tmp

So you end up with a __main__ module and a village module that contain
functions and classes built from the same code but with distinct identities.

In the account module you indirectly raise village.ExceptionWithLongName and
in __main__ you try to catch __main__.ExceptionWithLongName.

Peter
 
N

Nikola Skoric

Dana Sun, 20 Jun 2010 10:53:08 +0200,
Peter Otten said:
Now in your case village.py is first run as the main script and then [...]
In the account module you indirectly raise village.ExceptionWithLongName and
in __main__ you try to catch __main__.ExceptionWithLongName.

Phew. I get it now. You're my hero :-D I had to read it twice, but I
got it. Thanks a bunch!
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,019
Latest member
RoxannaSta

Latest Threads

Top