简体   繁体   中英

AttributeError in calling user-defined Python exception

I am trying to do exception handling mainly from Python's documentation . I am facing a weird problem: the directory contains main.py and exceptions.py .

In exceptions.py (with no import statements) I define my exception class as follows:

class ConvergenceError(AssertionError):
    def __init__(self,dc_places):
        self.decimal_places = dc_places
    def __str__(self):
        return 'convergence of R_inf is not correct to ', self.decimal_places

In main.py I have this import statement:

import exceptions as ex

and I call the exception as follows:

try:
    np.testing.assert_array_almost_equal(R_inf,R_itr,4)
    raise ex.ConvergenceError(4) 
except ex.ConvergenceError as ce :  
    print str(ce)

I receive the following error:

    except ex.ConvergenceError as ce :  
AttributeError: 'module' object has no attribute 'ConvergenceError'

I can not figure out why the interpreter can't see Convergence in the exceptions.py module.

As you have discussed with jonrsharpe , your problem is that you are actually importing a built-in module exceptions . Try the following:

>>> import exceptions
>>> exceptions
<module 'exceptions' (built-in)>

So what you can do is simply rename your module (eg to ex.py ) and you'll be good:

>>> import ex
...

I would just like to elaborate that exceptions is actually a C-builtin, and is loaded upon the start of the interpreter (this is only true on Python2 and not Python3, for Python3 it is found in builtins ):

 >>> import sys
 >>> [i for i in sys.modules if 'exceptions' in i]
 ['exceptions']
 >>> import exceptions   # dictionary lookup to builtin
 <module 'exceptions' (built-in)>

Exceptions has no path and is automatically in the current path for fairly obvious reasons: the interpreter itself, from the core libraries, requires exception handling. This means if you try to import exceptions via any standard approach, you will import the builtin and not your custom module you want.

For example, here I have exceptions.py in the path and try to load it via a standard import.

>>> [i for i in os.listdir(os.getcwd()) if 'except' in i]
['exceptions.py']
>>> import exceptions
<module 'exceptions' (built-in)>
exceptions = __import__("exceptions")
>>> exceptions
<module 'exceptions' (built-in)>

You cannot even reload it to force it into the interpreter.

>>> reload(exceptions)
<module 'exceptions' (built-in)>

You can absolutely force it if you use IMP and a custom full path.

>>> imp.load_source('exceptions', os.path.join(os.getcwd(), 'exceptions.py'))
<module 'exceptions' from '/home/alex/exceptions.py'>

EDIT: I should also mention that this does not override the builtin exceptions class except in the current namespace. Doing a from module import package still refers to the builtin even after the exceptions name has been overridden. Python wisely does not let you shoot yourself in the foot.

>>> exceptions
<module 'exceptions' from '/home/alex/exceptions.pyc'>
>>> from exceptions import BaseException
>>> BaseException
<type 'exceptions.BaseException'>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM