开发者

exception not getting caught when not in the right package in python

EDIT: OK, I managed to isolate the bug and the exact, complete code to to reproduce it. But it appears either something that's by design, or a bug in python.

Create two sibling packages: admin & General, each with it's own __init__.py, of course. In the package admin put the file 'test.py' with the following code:

from General.test02 import run
import RunStoppedException
try:
    run()
except RunStoppedException.RunStoppedException,e:
    print 'right'
except Exception,e:
    print 'this is what i got: %s'%type(e)

and also in admin put the file 'RunStoppedException.py' with the following code:开发者_如何学运维

class RunStoppedException(Exception):
    def __init__(self):
        Exception.__init__(self)

In the package General put the file test02.py with the code:

import admin.RunStoppedException
def run():
    raise admin.RunStoppedException.RunStoppedException()

the printout:

this is what i got: <class 'admin.RunStoppedException.RunStoppedException'>

When it should've been right. This only happens when one file sits in the same dir as the exception, so they import it differently.

Is this by design, or a bug of python?

I am using python2.6, running it under eclipse+pydev


import admin.RunStoppedException

This is an ambiguous relative import. Do you mean RunStoppedException from the admin top-level module? Or from mypackage.admin when you're in a package? If your current working directory (which is added to the module search path) happens to be inside the package, it could be either, depending on whether Python knows it's inside a package, which depends on how you're running the script.

If you've got both import admin.RunStoppedException and import RunStoppedException in different modules, that could very well import two copies of the same module: a top-level RunStoppedException and a submodule admin.RunStoppedException of the package admin, resulting in two instances of the exception, and the subsequent mismatch in except.

So don't use implicit relative imports. They are in any case going away (see PEP328). Always spell out the full module name, eg. import mypackage.admin.RunStoppedException. However avoid using the same identifier for your module name and your class name as this is terribly confusing. Note that Python will allow you to say:

except RunStoppedException:

where that identifier is referring to a module and not a subclass of Exception. This is for historical reasons and may also go away, but for the meantime it can hide bugs. A common pattern would be to use mypackage.exceptions to hold many exceptions. One-class-per-file is a Java habit that is frowned on in Python.

It's also a good idea generally try to keep the importing of module contents (like classes) down as much as possible. If something changes the copy of RunStoppedException inside the module, you'll now have different copies in different scripts. Though classes mostly don't change, module-level variables may, and monkey-patching and reloading become much harder when you're taking stuff outside of its owner module.


I can only see two reasons

  1. You have two different Exception classes with same name
    Edit: I think culprit is this part because you import Exception class two ways

    • from RunStoppedException import RunStoppedException
    • from admin.RunStoppedException import RunStoppedException

    make them consistent and your problem will be gone.

  2. You are using some IDE, which is interfering with your code, this sounds bizarre but try to run your code on command line if you aren't

Even 1 and 2 doesn't fix your problem, write a small piece of code demonstrating the problem, which we can run here, which we can fix, but I am sure we will not need to because once you have written such a small standalone script where you can replicate the problem you will find the solution too.


Works fine for me:

[/tmp] ls admin/
RunStoppedException.py  __init__.py     test.py
RunStoppedException.pyc __init__.pyc
[/tmp] ls General/
__init__.py __init__.pyc    test02.py   test02.pyc
[/tmp] python -m admin.test 
right
[/tmp] 

Running on:

Python 2.6.4 Stackless 3.1b3 060516 (release26-maint, Dec 14 2009, 23:28:06) 
[GCC 4.2.1 (Apple Inc. build 5646) (dot 1)] on darwin

My guess is that you have another "General" on your path somewhere, perhaps from earlier tests, and thats why the exceptions don't match. Did you try the id/inspect.getabsfile debugging? If so, what was the output?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜